Sql 连接三个表并尝试获取空值
我有三张表:tblProduct、LKPoodGroup、tblCustomer。和一个连接表:jctCustomerFoodgroup 这些列如下所示:Sql 连接三个表并尝试获取空值,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有三张表:tblProduct、LKPoodGroup、tblCustomer。和一个连接表:jctCustomerFoodgroup 这些列如下所示: **tblProduct** +---+----------------+ |PK |int_ProductID | |FK |int_FoodgroupID | | |str_ProductName | +---+----------------+ **lkpFoodgroup** +---+-------------------
**tblProduct**
+---+----------------+
|PK |int_ProductID |
|FK |int_FoodgroupID |
| |str_ProductName |
+---+----------------+
**lkpFoodgroup**
+---+-------------------+
|PK |int_FoodgroupID |
| |str_FoodgroupHandle|
+---+-------------------+
**tblCustomer**
+---+----------------+
|PK |int_CustomerID |
| |str_CustomerName|
+---+----------------+
**jctCustomerFoodgroup**
+---+----------------+
|PK |int_CustomerID |
|PK |int_FoodgroupID |
| |int_ProductID |
+---+----------------+
这些表中最简单的是查找:
**lkpFoodgroup**
+---------------+-------------------+
|int_FoodgroupID|str_FoodgroupHandle|
+---------------+-------------------+
|1 |fruit |
|2 |meat |
|3 |bread |
|4 |cheese |
+---------------+-------------------+
其次是客户:
**tblCustomer**
+----------------+-------------------+
|int_CustomerID |str_CustomerName |
+----------------+-------------------+
|1 |Bob |
|2 |Sally |
|3 |Jane |
|4 |Billy |
+----------------+-------------------+
TBLPProduct上可能有许多产品具有相同的Foodgroup。此外,也可能存在一些没有产品的产品食物组:
**tblProduct**
+---------------+-----------------+----------------+
|int_ProductID |int_FoodgroupID |str_ProductName |
+---------------+-----------------+----------------+
|1 |1 |apple |
|2 |1 |banana |
|3 |1 |orange |
|4 |1 |pear |
|5 |2 |chicken |
|6 |2 |beef |
|7 |2 |fish |
|8 |2 |turkey |
|9 |3 |white |
|10 |3 |wheat |
+---------------+-----------------+----------------+
连接表上的主键是int_CustomerID和int_FoodgroupID的组合-这意味着任何客户只能为每个foodgroups选择一种产品:
**jctCustomerFoodgroup**
+---------------+-----------------+--------------+------------------------+
|int_CustomerID |int_FoodgroupID |int_ProductID | --meaning |
+---------------+-----------------+--------------+------------------------|
|1 | 1 |1 | --Bob, fruit, apple |
|1 | 2 |6 | --Bob, meat, beef |
|1 | 3 |9 | --Bob, bread, white |
|2 | 1 |3 | --Sally, fruit, orange |
|2 | 2 |5 | --Sally, meat, chicken |
|3 | 1 |3 | --Jane, fruit, orange |
|3 | 3 |9 | --Jane, bread, white |
|3 | 2 |6 | --Jane, meat, beef |
+---------------+-----------------+--------------+------------------------+
我正在寻找一个查询,它将为我提供如下结果:
**spGetCustomerProductSelections(1) --Get Bob's choices**
+----------------+---------------+-------------------+-------------+---------------+
|int_CustomerID |int_FoodgroupID|str_FoodgroupHandle|int_ProductID|str_ProductName|
+----------------+---------------+-------------------+-------------+---------------+
|1 |1 |fruit |1 |apple |
|1 |2 |meat |6 |beef |
|1 |3 |bread |9 |white |
|1 |4 |cheese |null |null |
+----------------+---------------+-------------------+-------------+---------------+
**spGetCustomerProductSelections(2) --Get Sally's choices**
+----------------+---------------+-------------------+-------------+---------------+
|int_CustomerID |int_FoodgroupID|str_FoodgroupHandle|int_ProductID|str_ProductName|
+----------------+---------------+-------------------+-------------+---------------+
|2 |1 |fruit |3 |orange |
|2 |2 |meat |5 |chicken |
|2 |3 |bread |null |null |
|2 |4 |cheese |null |null |
+----------------+---------------+-------------------+-------------+---------------+
**spGetCustomerProductSelections(4) --Get Billy's choices**
+----------------+---------------+-------------------+-------------+---------------+
|int_CustomerID |int_FoodgroupID|str_FoodgroupHandle|int_ProductID|str_ProductName|
+----------------+---------------+-------------------+-------------+---------------+
|4 |1 |fruit |null |null |
|4 |2 |meat |null |null |
|4 |3 |bread |null |null |
|4 |4 |cheese |null |null |
+----------------+---------------+-------------------+-------------+---------------+
有什么帮助吗?您应该使用外部联接(左、右或全)。这些联接将包括空值。请不要将您的过程命名为以“sp”开头。它将开始在主数据库中搜索,直到稍后返回到您的数据库 模式和数据的DDL
create table lkpFoodgroup
(int_FoodgroupID int, str_FoodgroupHandle varchar(max))
insert lkpFoodgroup values
(1,'fruit'),
(2,'meat'),
(3,'bread'),
(4,'cheese');
create table tblCustomer
(int_CustomerID int, str_CustomerName varchar(max))
insert tblCustomer values
(1,'Bob'),
(2,'Sally'),
(3,'Jane'),
(4,'Billy');
create table tblProduct
(int_ProductID int, int_FoodgroupID int, str_ProductName varchar(max))
insert tblProduct values
(1,'1','apple'),
(2,'1','banana'),
(3,'1','orange'),
(4,'1','pear'),
(5,'2','chicken'),
(6,'2','beef'),
(7,'2','fish'),
(8,'2','turkey'),
(9,'3','white'),
(10,'3','wheat');
create table jctCustomerFoodgroup
(int_CustomerID int, int_FoodgroupID int, int_ProductID varchar(max))
insert jctCustomerFoodgroup values
(1,'1','1'),
(1,'2','6'),
(1,'3','9'),
(2,'1','3'),
(2,'2','5'),
(3,'1','3'),
(3,'3','9'),
(3,'2','6');
存储的过程代码
create proc uspGetCustomerProductSelections @customerID int as
select c.int_CustomerID, l.int_FoodgroupID, l.str_FoodgroupHandle, j.int_ProductID, p.str_ProductName
from tblCustomer c
cross join lkpFoodgroup l
left join jctCustomerFoodgroup j on j.int_CustomerID = c.int_CustomerID and j.int_FoodgroupID = l.int_FoodgroupID
left join tblProduct p on p.int_ProductID = j.int_ProductID
where c.int_CustomerID = @customerID
样本执行
exec uspGetCustomerProductSelections 1
输出
int_CustomerID int_FoodgroupID str_FoodgroupHandle int_ProductID str_ProductName
-------------- --------------- ---------------------------------------------------
1 1 fruit 1 apple
1 2 meat 6 beef
1 3 bread 9 white
1 4 cheese NULL NULL
如果您生成的是create和insert语句,而不仅仅是数据,您将获得更大的吸引力。?因为ProductID是product的主键,连接表CustomerFoodGroup应该是CustomerProduct,只有ProductID,除非您有允许您针对不同的食品组购买产品的业务规则。是的,我认为规则是我不能命名它们sp_u-我认为sp很好。非常感谢您的回答cyberkiwi。也不需要匈牙利符号。你不需要仅仅因为它是一个表就用
tbl
前缀来命名它;使用有意义的名称。它在技术上和功能上都是无用的,但是WRT代码的可读性和可读性是有目的的。它也是我们开发标准的一部分。当您使用匈牙利符号来表示并非“仅”表的表时,匈牙利符号确实起到了一定的作用,例如连接和查找。