2013-02-01 57 views
2

下面的代碼獲取包含車輛名稱的表格以及包含區域名稱的表格,並將它們合併到結果表格中。 然後我在結果表上執行一個COUNT來顯示每個區域有多少輛車。強制零出現在計數

我需要修改代碼以強制所有區域和所有車輛進行計數。目前,COUNT語句不顯示任何不包含車輛的區域(我已經手動刪除了結果中的一些條目以顯示此內容)。任何人都可以說明一個快速方法來做到這一點?我使用SQL 2012,希望會有一個簡單的解決方案...

enter image description here

爲了回答這個問題,請假設兩個原始表不再訪問的目的,現在我們只工作與@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 

回答

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 
+0

不會'COUNT(*)'弄亂結果嗎?你應該在'@ tbl_results'表的某個列上做點數 – Lamak

+0

@Lamak:你說的沒錯,count(*)'錯誤地返回1,如果沒有找到某個地區的行+車輛組 – Andomar

+0

超級謝謝。我將連接列更改爲ID列(只是爲了消除任何可能的兩個車輛/區域具有相同的名稱,但具有不同的ID)並且它工作良好。 – EvilDr

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 
+0

沒有'distinct'的'cross join'會導致很多重複的行。該查詢將返回過高的計數。 – Andomar

+0

@Andomar那麼,因爲這些表是獨一無二的,我真的不知道這個問題。但是,如果他們不是,那麼這將顯示重複的結果。 – Lamak

+0

啊,你加入'@ tbl_vehicles'而不是'@ tbl_results'。更好的是,+1 – Andomar

0

您可以用左連接和參考isNull的組合實現你的目標。總體思路如下:

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

您可以添加詳細信息。

+0

count(*)永遠不會爲空 – Tobsey

+0

與Tobsey達成一致。計數將始終返回一個值或0-零。不需要isNulll()或NVL() – Art

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 

Fiddle

在我使用的表,而不是表變量的小提琴,但這個想法表示。創建一個包含所有車輛和區域對的公共表達式。然後做一個Count(結果。[AnyColumn])。如果你做一個Count(*),那麼結果中的NULL值將被計數。你不想那樣。您只需要計算結果中包含值的位置。

+0

好的,也適用 - 謝謝你:-) – EvilDr