如何根据两个参数连接两个以上的表?
How to join more than two tables on the basis of two parameters?
我有三个表 #temp
、tbProducts
和 tbVendor
tbVendor(States, AgentId, Products)
tbProduct(ProductId, ProductName)
#temp(ProductName)
示例数据
tbVendor
-------------------------------- ----------- --------------------
States AgentId Products
-------------------------------- ----------- --------------------
Alabama,New York 1 T.V, Desktops
New Jersy, Florida 2 Cellphones, Laptops
New York, San Fransico 1 Cellphones, Desktop
New Jersy, San Fransico 1 A.C, Heaters
tbProduct
----------- -------------
ProductId ProductName
----------- -------------
1 T.V
2 Laptops
3 Desktop
4 Cellphones
5 A.C
6 Heaters
#temp
---------------
ProductName
---------------
T.V
Laptops
Desktop
Cellphones
A.C
Heaters
现在我已经对它们执行连接操作以获取 ProductId
和 ProductName
根据 Agent Id
和 States
字段分配 tbVendor
。
例如,我已经获取了所有 Products
及其 Names
和 Ids
在 New york
和 AgentId = 1
中,输出应该像
ProductId ProductName
----------- -------------
1 T.V
3 Desktop
4 Cellphones
请注意 #Temp
包含分配给 AgentId = 1
的所有产品。我以某种方式设法获取了分配给 AgentId = 1
的所有产品以及 #temp
表中的所有产品。现在我无法设法获取输出,例如仅分配给 New York
的产品预期输出如下所示
ProductId ProductName
----------- -------------
1 T.V
3 Desktop
4 Cellphones
我已经尝试了下面的代码行,但它不起作用
Select * from tbProduct L
JOIN #Temp TL ON L.ProductName collate SQL_Latin1_General_CP1_CI_AS = TL.ProductName
JOIN tbVendor Li ON Li.AgentId = @AgentId and Li.States like @States;
请注意,@States
包含 New York
,@AgentId
包含 1
。
试试这个:
DECLARE @state varchar(25) = 'New York',
@agentId int = 1
SELECT STUFF((SELECT ', ' + Products
FROM tbVendor tv
WHERE tv.AgentId = @agentId AND tv.States Like '%' +@state + '%'
FOR XML PATH('')), 1, 2, '') AS products
INTO #tmp
;with tmp(product, products) as (
select LTRIM(LEFT(products, CHARINDEX(', ',products+', ')-1)),
STUFF(products, 1, CHARINDEX(', ',products+', '), '')
from #tmp
union all
select LTRIM(LEFT(products, CHARINDEX(', ',products+', ')-1)),
STUFF(products, 1, CHARINDEX(', ',products+', '), '')
from tmp
where products > ''
)
SELECT tp.*
FROM tbProduct tp
INNER JOIN tmp t ON t.product = tp.ProductName
将 CSV 拆分成行
;WITH CTE AS
(
-- Split States
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT(0))) RNO,
AgentId,
LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'STATE'
FROM
(
-- Use 3 REPLACE for '|', ';', ','
SELECT AgentId,
CAST ('<M>' + REPLACE([STATE], ',', '</M><M>') + '</M>' AS XML) AS Data
FROM #tbVendor
) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
)
SELECT C1.AGENTID,C1.[STATE],TAB.Products,P.ProductID
FROM CTE C1
JOIN
(
-- Split Products
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT(0))) RNO, AgentId,
LTRIM(RTRIM(Split.A.value('.', 'VARCHAR(100)'))) 'Products'
FROM
(
-- Use 3 REPLACE for '|', ';', ','
SELECT AgentId,
CAST ('<M>' + REPLACE(Products, ',', '</M><M>') + '</M>' AS XML) AS Data
FROM #tbVendor
) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
)TAB
ON C1.RNO=TAB.RNO AND C1.AGENTID=TAB.AGENTID
-- Get Product Id
JOIN #tbProduct P
ON TAB.Products=P.ProductName
WHERE ...your conditions...
现在您将获得所有 states
以及 ProductId
、ProductName
和 AgentId
写成:
;WITH cte AS (
SELECT
AgentId,
CAST('<r>' + REPLACE(States, ',', '</r><r>') + '</r>' AS XML) AS States,
CAST('<r>' + REPLACE(Products, ',', '</r><r>') + '</r>' AS XML) AS Products
FROM @tbVendor
)
,FinalList AS (
SELECT
AgentId,
RTRIM(LTRIM (sTable.sColumn.value('.', 'VARCHAR(MAX)'))) AS States,
RTRIM(LTRIM (PTable.PColumn.value('.', 'VARCHAR(MAX)'))) AS Products
FROM cte
CROSS APPLY States.nodes('//r') AS sTable(sColumn)
CROSS APPLY Products.nodes('//r') AS PTable(PColumn)
)
SELECT DISTINCT F.Products AS ProductName
,T.ProductId AS ProductId
FROM FinalList F
CROSS APPLY (SELECT ProductId FROM @tbProduct TP WHERE TP.ProductName = F.Products) AS T
WHERE F.States = 'New York'
AND F.AgentId = 1
ORDER BY T.ProductId ASC
更新:处理特殊字符 LIKE &
将其替换为 &
为:
;WITH cte AS (
SELECT
AgentId,
CAST('<r>' + REPLACE(States, ',', '</r><r>') + '</r>' AS XML) AS States,
CAST('<r>' + REPLACE(REPLACE(Products,'&','&'), ',', '</r><r>') + '</r>' AS XML) AS Products
FROM @tbVendor
)
,FinalList AS (
SELECT
AgentId,
RTRIM(LTRIM (sTable.sColumn.value('.', 'VARCHAR(MAX)'))) AS States,
RTRIM(LTRIM (PTable.PColumn.value('.', 'VARCHAR(MAX)'))) AS Products
FROM cte
CROSS APPLY States.nodes('//r') AS sTable(sColumn)
CROSS APPLY Products.nodes('//r') AS PTable(PColumn)
)
SELECT DISTINCT F.Products AS ProductName
,T.ProductId AS ProductId
FROM FinalList F
CROSS APPLY (SELECT ProductId FROM @tbProduct TP WHERE TP.ProductName = F.Products) AS T
WHERE F.States = 'New York'
AND F.AgentId = 1
ORDER BY T.ProductId ASC
我有三个表 #temp
、tbProducts
和 tbVendor
tbVendor(States, AgentId, Products)
tbProduct(ProductId, ProductName)
#temp(ProductName)
示例数据
tbVendor
-------------------------------- ----------- --------------------
States AgentId Products
-------------------------------- ----------- --------------------
Alabama,New York 1 T.V, Desktops
New Jersy, Florida 2 Cellphones, Laptops
New York, San Fransico 1 Cellphones, Desktop
New Jersy, San Fransico 1 A.C, Heaters
tbProduct
----------- -------------
ProductId ProductName
----------- -------------
1 T.V
2 Laptops
3 Desktop
4 Cellphones
5 A.C
6 Heaters
#temp
---------------
ProductName
---------------
T.V
Laptops
Desktop
Cellphones
A.C
Heaters
现在我已经对它们执行连接操作以获取 ProductId
和 ProductName
根据 Agent Id
和 States
字段分配 tbVendor
。
例如,我已经获取了所有 Products
及其 Names
和 Ids
在 New york
和 AgentId = 1
中,输出应该像
ProductId ProductName
----------- -------------
1 T.V
3 Desktop
4 Cellphones
请注意 #Temp
包含分配给 AgentId = 1
的所有产品。我以某种方式设法获取了分配给 AgentId = 1
的所有产品以及 #temp
表中的所有产品。现在我无法设法获取输出,例如仅分配给 New York
的产品预期输出如下所示
ProductId ProductName
----------- -------------
1 T.V
3 Desktop
4 Cellphones
我已经尝试了下面的代码行,但它不起作用
Select * from tbProduct L
JOIN #Temp TL ON L.ProductName collate SQL_Latin1_General_CP1_CI_AS = TL.ProductName
JOIN tbVendor Li ON Li.AgentId = @AgentId and Li.States like @States;
请注意,@States
包含 New York
,@AgentId
包含 1
。
试试这个:
DECLARE @state varchar(25) = 'New York',
@agentId int = 1
SELECT STUFF((SELECT ', ' + Products
FROM tbVendor tv
WHERE tv.AgentId = @agentId AND tv.States Like '%' +@state + '%'
FOR XML PATH('')), 1, 2, '') AS products
INTO #tmp
;with tmp(product, products) as (
select LTRIM(LEFT(products, CHARINDEX(', ',products+', ')-1)),
STUFF(products, 1, CHARINDEX(', ',products+', '), '')
from #tmp
union all
select LTRIM(LEFT(products, CHARINDEX(', ',products+', ')-1)),
STUFF(products, 1, CHARINDEX(', ',products+', '), '')
from tmp
where products > ''
)
SELECT tp.*
FROM tbProduct tp
INNER JOIN tmp t ON t.product = tp.ProductName
将 CSV 拆分成行
;WITH CTE AS
(
-- Split States
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT(0))) RNO,
AgentId,
LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'STATE'
FROM
(
-- Use 3 REPLACE for '|', ';', ','
SELECT AgentId,
CAST ('<M>' + REPLACE([STATE], ',', '</M><M>') + '</M>' AS XML) AS Data
FROM #tbVendor
) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
)
SELECT C1.AGENTID,C1.[STATE],TAB.Products,P.ProductID
FROM CTE C1
JOIN
(
-- Split Products
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT(0))) RNO, AgentId,
LTRIM(RTRIM(Split.A.value('.', 'VARCHAR(100)'))) 'Products'
FROM
(
-- Use 3 REPLACE for '|', ';', ','
SELECT AgentId,
CAST ('<M>' + REPLACE(Products, ',', '</M><M>') + '</M>' AS XML) AS Data
FROM #tbVendor
) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
)TAB
ON C1.RNO=TAB.RNO AND C1.AGENTID=TAB.AGENTID
-- Get Product Id
JOIN #tbProduct P
ON TAB.Products=P.ProductName
WHERE ...your conditions...
现在您将获得所有 states
以及 ProductId
、ProductName
和 AgentId
写成:
;WITH cte AS (
SELECT
AgentId,
CAST('<r>' + REPLACE(States, ',', '</r><r>') + '</r>' AS XML) AS States,
CAST('<r>' + REPLACE(Products, ',', '</r><r>') + '</r>' AS XML) AS Products
FROM @tbVendor
)
,FinalList AS (
SELECT
AgentId,
RTRIM(LTRIM (sTable.sColumn.value('.', 'VARCHAR(MAX)'))) AS States,
RTRIM(LTRIM (PTable.PColumn.value('.', 'VARCHAR(MAX)'))) AS Products
FROM cte
CROSS APPLY States.nodes('//r') AS sTable(sColumn)
CROSS APPLY Products.nodes('//r') AS PTable(PColumn)
)
SELECT DISTINCT F.Products AS ProductName
,T.ProductId AS ProductId
FROM FinalList F
CROSS APPLY (SELECT ProductId FROM @tbProduct TP WHERE TP.ProductName = F.Products) AS T
WHERE F.States = 'New York'
AND F.AgentId = 1
ORDER BY T.ProductId ASC
更新:处理特殊字符 LIKE &
将其替换为 &
为:
;WITH cte AS (
SELECT
AgentId,
CAST('<r>' + REPLACE(States, ',', '</r><r>') + '</r>' AS XML) AS States,
CAST('<r>' + REPLACE(REPLACE(Products,'&','&'), ',', '</r><r>') + '</r>' AS XML) AS Products
FROM @tbVendor
)
,FinalList AS (
SELECT
AgentId,
RTRIM(LTRIM (sTable.sColumn.value('.', 'VARCHAR(MAX)'))) AS States,
RTRIM(LTRIM (PTable.PColumn.value('.', 'VARCHAR(MAX)'))) AS Products
FROM cte
CROSS APPLY States.nodes('//r') AS sTable(sColumn)
CROSS APPLY Products.nodes('//r') AS PTable(PColumn)
)
SELECT DISTINCT F.Products AS ProductName
,T.ProductId AS ProductId
FROM FinalList F
CROSS APPLY (SELECT ProductId FROM @tbProduct TP WHERE TP.ProductName = F.Products) AS T
WHERE F.States = 'New York'
AND F.AgentId = 1
ORDER BY T.ProductId ASC