左联接不同的表和计数

时间:2020-03-02 18:02:51

标签: sql sql-server

我有3张桌子。以下是示例表,以方便参考。

drop table if exists #itemmaster
drop table if exists #sales
drop table if exists #transfer

CREATE TABLE #itemmaster(ItemID float, ItemName varchar(10))
insert into #itemmaster values
(1,'A'),
(2,'B'),
(3,'C'),
(4,'D'),
(5,'E'),
(6,'F'),
(7,'G'),
(8,'H')

CREATE TABLE #sales(ItemID float)
insert into #sales values
(1),
(5),
(2),
(5),
(5),
(4),
(1),
(1),
(8),
(4),
(7)

CREATE TABLE #transfer(ItemID float)
insert into #transfer values
(2),
(5),
(5),
(4),
(1),
(1),
(7)

我正在尝试获得以下结果。

+--------+--------------+-----------------+
| ItemID | CountOfSales | CountOfTransfer |
+--------+--------------+-----------------+
|      1 |            3 |               2 |
|      2 |            1 |               1 |
|      3 |            0 |               0 |
|      4 |            2 |               1 |
|      5 |            3 |               2 |
|      6 |            0 |               0 |
|      7 |            1 |               1 |
|      8 |            1 |               0 |

我正在运行以下查询,但是它给了我错误的结果。 我不确定为什么左联接计数计算会给我错误的输出。 请帮助解决和了解该方法。

select i.ItemID, count(s.itemid) as CountOfSales, count(t.itemid) as CountOfTransfer
from #itemmaster I
left join #sales S on i.itemid = S.itemid
left join #transfer T on i.itemid = t.itemid
group by i.itemid

2 个答案:

答案 0 :(得分:1)

在这种情况下,相关子查询可能非常方便:

 select i.*,
           (select count(*)
            from #sales S 
            where i.itemid = S.itemid
           ) as CountOfSales,
           (select count(*)
            from #transfer t
            where i.itemid = t.itemid
           ) as CountOfTransfer
    from #itemmaster i;

如果#sales#transferitemid上有索引,那么这可能也是最快的解决方案。

答案 1 :(得分:1)

一种选择是使用一些子查询来简化要加入的Sales和Transfer表,然后将这些结果左移回item表中。在这段代码中,我使用的是CTE(公用表表达式),而不仅仅是主FROM语句中的子查询,以提高可读性和整洁度。


-- First get the Sales totals
WITH SalesTotals AS (
    SELECT
        S.ItemID,
        COUNT(*) AS SaleCount
    FROM
        #sales AS S
    GROUP BY
        S.ItemID
),
-- Then get the Transfer Totals
TransferTotals AS (
    SELECT
        T.ItemID,
        COUNT(*) AS TransferCount
    FROM
        #transfer AS T
    GROUP BY
        T.ItemID
)
-- Join the SalesTotals and TransferTotals to the ItemMaster table
SELECT 
    I.ItemID,
    ISNULL(ST.SaleCount, 0) AS CountOfSales,
    ISNULL(TT.TransferCount, 0) AS CountOfTransfer
FROM
    #itemmaster AS I
    LEFT JOIN SalesTotals AS ST ON I.ItemID = ST.ItemID
    LEFT JOIN TransferTotals AS TT ON I.ItemID = TT.ItemID