【问题标题】:SQL select customers, items from transactions with and without transactionSQL 从有交易和无交易的交易中选择客户、商品
【发布时间】:2016-06-21 19:11:44
【问题描述】:

我在 SQL Server、Customers、Items 和 Transactions 中有 3 个表。表 Transactions 中的 C_id 和 I.id 是表 Customers 和 Items 的外键。我想要一个特定的日期范围来查看所有客户,所有带有数量的物品,无论是否有交易。商品未成交时,数量为0。

客户 (C)

id    |  Name
1     |  C1
2     |  C2
3     |  C3

物品 (I)

id   |  Name
1    |  I1
2    |  I2
3    |  I3
4    |  I4

交易

id   |   C_id  |   I_id   |  qty   | date
1    |   C1    |   I1     |  10    | 2/2/2016
2    |   C2    |   I3     |   5    | 3/2/2016
3    |   C1    |   I2     |   3    | 3/2/2016
4    |   C2    |   I1     |   8    | 4/2/2016
5    |   C1    |   I1     |   2    | 5/2/2016
6    |   C1    |   I2     |   4    | 5/2/2016
7    |   C2    |   I1     |   2    | 6/2/2016
8    |   C1    |   I1     | 100    | 1/3/2016
9    |   C2    |   I2     | 200    | 2/3/2016

我想要的 2/2/2016 和 10/2/2016 之间的数据范围的结果是:

C   |  I    | qty
C1  |  I1   | 12
C1  |  I2   | 7
C1  |  I3   | 0
C1  |  I4   | 0
C2  |  I1   | 10
C2  |  I2   | 0
C2  |  I3   | 5
C2  |  I4   | 0
C3  |  I1   | 0
C3  |  I2   | 0
C3  |  I3   | 0
C4  |  I4   | 0

【问题讨论】:

  • 交叉连接、左连接、分组方式

标签: sql-server


【解决方案1】:

如果您想要包含所有商品的所有客户的完整列表,那么您将需要交叉连接这两个表。然后,您可以使用您之后的日期范围对事务表进行左连接。

让我们制作你的测试数据;

IF OBJECT_ID('tempdb..#Customers') IS NOT NULL DROP TABLE #Customers
GO
CREATE TABLE #Customers (id int, Name varchar(2))
INSERT INTO #Customers (id, Name)
VALUES
(1,'C1')
,(2,'C2')
,(3,'C3')

IF OBJECT_ID('tempdb..#Items') IS NOT NULL DROP TABLE #Items
GO
CREATE TABLE #Items (id int, Name varchar(2))
INSERT INTO #Items (id, Name)
VALUES
(1,'I1')
,(2,'I2')
,(3,'I3')
,(4,'I4')

IF OBJECT_ID('tempdb..#Transactions') IS NOT NULL DROP TABLE #Transactions
GO
CREATE TABLE #Transactions (id int, C_id varchar(2), I_id varchar(2), qty int, date datetime)
INSERT INTO #Transactions (id, C_id, I_id, qty, date)
VALUES
(1,'C1','I1',10,'2016-02-02')
,(2,'C2','I3',5,'2016-02-03')
,(3,'C1','I2',3,'2016-02-03')
,(4,'C2','I1',8,'2016-02-04')
,(5,'C1','I1',2,'2016-02-05')
,(6,'C1','I2',4,'2016-02-05')
,(7,'C2','I1',2,'2016-02-06')
,(8,'C1','I1',100,'2016-03-01')
,(9,'C2','I2',200,'2016-03-02')

还有你需要的查询;

DECLARE @StartDate datetime; SET @StartDate = '2016-02-02'
DECLARE @EndDate datetime; SET @EndDate = '2016-02-10'

SELECT
c.Name Cust_ID
,i.Name Item_ID
,SUM(ISNULL(t.qty,0)) Qty
FROM #Customers c
CROSS JOIN #Items i
LEFT JOIN #Transactions t
    ON c.Name = t.C_id
    AND i.Name = t.I_id
    AND t.date BETWEEN @StartDate AND @EndDate
GROUP BY c.Name, i.Name
ORDER BY c.Name, i.Name

给出这些结果;

Cust_ID Item_ID Qty
C1      I1      12
C1      I2      7
C1      I3      0
C1      I4      0
C2      I1      10
C2      I2      0
C2      I3      5
C2      I4      0
C3      I1      0
C3      I2      0
C3      I3      0
C3      I4      0

【讨论】:

  • 很高兴它有帮助。随意对您认为有用的任何答案进行投票,并将其中一个标记为已接受的答案。谢谢
【解决方案2】:

试试这个,希望对你有帮助。,

select c.name,i.name,sum(isnull(t.qty,0))
from customers c
cross join Items I 
left join transactions t on t.C_Id = C.Id and I.Id = t.I_Id and t.date between '2/2/2016' and '10/2/2016'
group by c.name,i.name
order by c.name,i.name

【讨论】:

  • When the item has not transaction the quantity will be 0.
  • 我们只有交易表中的日期。因此,当我们使用 Date 过滤值时,该项目必须是已交易的。
  • 这个查询只返回有交易的商品。我不想要这个。它不会为所有没有交易的客户退回商品。
猜你喜欢
  • 2011-01-21
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多