2

以下代码采用一个包含车辆名称的表和一个包含区域名称的表,并将它们组合成一个结果表。然后我对结果表执行 COUNT 以显示每个区域有多少车辆。

我需要修改代码以强制计算所有地区和所有车辆。目前 COUNT 语句不显示任何不包含车辆的区域(我已从结果中手动删除了一些条目以显示这一点)。谁能说明一个快速的方法来做到这一点?我正在使用 SQL 2012,并希望有一个简单的解决方案......

在此处输入图像描述

为了回答这个问题,请假设两个原始表不再可访问,我们现在只使用@tbl_results。谢谢你。

注意:我知道我可以直接从车辆和区域表中执行此操作,但我需要在实际工作中为其他流程使用结果表变量。

DECLARE @tbl_vehicles TABLE (vehicleID int, vehicleName nvarchar(100))
DECLARE @tbl_regions TABLE (regionID int, regionName nvarchar(100))
DECLARE @tbl_results TABLE (regionID int, regionName nvarchar(100), vehicleID int, vehicleName nvarchar(100))

INSERT INTO @tbl_regions (regionID, regionName) VALUES (1, 'England')
INSERT INTO @tbl_regions (regionID, regionName) VALUES (2, 'United States')
INSERT INTO @tbl_regions (regionID, regionName) VALUES (3, 'Arctic')

INSERT INTO @tbl_vehicles (vehicleID, vehicleName) VALUES (1, 'Planes')
INSERT INTO @tbl_vehicles (vehicleID, vehicleName) VALUES (2, 'Trains')
INSERT INTO @tbl_vehicles (vehicleID, vehicleName) VALUES (3, 'Automobiles')

DECLARE @i INT
SET @i = 0 

WHILE @i < 100
    BEGIN
        INSERT INTO @tbl_results
            (regionID, regionName, vehicleID, vehicleName) 
        SELECT
            r.regionID, r.regionName, v.vehicleID, v.vehicleName 
        FROM
            @tbl_regions r CROSS JOIN
            @tbl_vehicles v 
        WHERE
            (r.regionID = CAST(RAND() * 4 AS INT)) AND
            (v.vehicleID = CAST(RAND() * 4 AS INT)) 
        SET @i = @i + 1
    END

-- remove trains in the arctic for count example
DELETE FROM @tbl_results WHERE (regionID=3) AND (vehicleID=2)

-- this statement needs to include ALL vehicles and ALL regions (even if no vehicles are found at a region)
SELECT 
    regionName,
    vehicleName,
    COUNT(*) as VehicleCount
FROM
    @tbl_results 
GROUP BY
    regionID,
    regionName,
    vehicleID,
    vehicleName
ORDER BY regionName, vehicleName  
4

4 回答 4

2
SELECT  r.regionName
,       v.vehicleName
,       COUNT(res.vehicleName) as VehicleCount
FROM    (
        select  distinct regionName
        from    @tbl_results
        ) r
CROSS JOIN 
        (
        select  distinct vehicleName
        from    @tbl_results
        ) v
LEFT OUTER JOIN
        @tbl_results res
ON      r.regionName = res.regionName
        AND v.vehicleName = res.vehicleName
GROUP BY
        r.regionName
,       v.vehicleName
ORDER BY
        r.regionName
,       v.vehicleName
于 2013-02-01T12:46:33.357 回答
1

尝试这个:

DECLARE @tbl_vehicles TABLE (vehicleID int, vehicleName nvarchar(100))
DECLARE @tbl_regions TABLE (regionID int, regionName nvarchar(100))
DECLARE @tbl_results TABLE (regionID int, regionName nvarchar(100), 
                            vehicleID int, vehicleName nvarchar(100))

INSERT INTO @tbl_regions (regionID, regionName) VALUES (1, 'England')
INSERT INTO @tbl_regions (regionID, regionName) VALUES (2, 'United States')
INSERT INTO @tbl_regions (regionID, regionName) VALUES (3, 'Arctic')

INSERT INTO @tbl_vehicles (vehicleID, vehicleName) VALUES (1, 'Planes')
INSERT INTO @tbl_vehicles (vehicleID, vehicleName) VALUES (2, 'Trains')
INSERT INTO @tbl_vehicles (vehicleID, vehicleName) VALUES (3, 'Automobiles')

DECLARE @i INT
SET @i = 0 

WHILE @i < 100
    BEGIN
        INSERT INTO @tbl_results
            (regionID, regionName, vehicleID, vehicleName) 
        SELECT
            r.regionID, r.regionName, v.vehicleID, v.vehicleName 
        FROM
            @tbl_regions r CROSS JOIN
            @tbl_vehicles v 
        WHERE
            (r.regionID = CAST(RAND() * 4 AS INT)) AND
            (v.vehicleID = CAST(RAND() * 4 AS INT)) 
        SET @i = @i + 1
    END

-- remove trains in the arctic for count example
DELETE FROM @tbl_results WHERE (regionID=3) AND (vehicleID=2)

-- this statement needs to include ALL vehicles 
-- and ALL regions (even if no vehicles are found at a region)
SELECT 
    R.regionName,
    VE.vehicleName,
    ISNULL(COUNT(RES.regionID),0) as VehicleCount
FROM @tbl_regions R
CROSS JOIN @tbl_vehicles VE
LEFT JOIN @tbl_results RES
    ON R.regionID = RES.regionID AND VE.vehicleID = RES.vehicleID
GROUP BY
     R.regionName,
    VE.vehicleName
ORDER BY R.regionName, VE.vehicleName  
于 2013-02-01T12:47:52.623 回答
1

我会这样做:

WITH VehicleRegions AS
(
  SELECT
    *
  FROM
    tbl_vehicles,
    tbl_regions
 )
SELECT 
  VehicleRegions.VehicleName,
  VehicleRegions.RegionName,
  COUNT(tbl_results.regionID)
FROM
  VehicleRegions
  LEFT JOIN tbl_results ON VehicleRegions.VehicleID = tbl_results.VehicleID AND VehicleRegions.RegionID = tbl_results.RegionID
GROUP BY
  VehicleRegions.VehicleName,
  VehicleRegions.RegionName

小提琴

在小提琴中,我使用了表而不是表变量,但这个想法是成立的。创建一个包含所有车辆和区域对的公用表表达式。然后做一个计数(结果。[AnyColumn])。如果您执行 Count(*),则结果中的 NULL 值将被计算在内。你不想要那个。您只想计算结果包含值的位置。

于 2013-02-01T13:18:16.817 回答
0

您可以通过结合使用 left join 和 isNull 来实现您的目标。总体思路如下:

select f1, f2, isNull(count(*), 0) records
from t1 left join t2 on something
where whatever
group by f1, f2

您可以添加详细信息。

于 2013-02-01T13:13:53.970 回答