如何根据两个参数连接两个以上的表?

How to join more than two tables on the basis of two parameters?

我有三个表 #temptbProductstbVendor

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

现在我已经对它们执行连接操作以获取 ProductIdProductName
根据 Agent IdStates 字段分配 tbVendor

例如,我已经获取了所有 Products 及其 NamesIdsNew yorkAgentId = 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 以及 ProductIdProductNameAgentId

写成:

;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 & 将其替换为 &amp; 为:

;WITH cte AS (
    SELECT 
        AgentId,
        CAST('<r>' + REPLACE(States, ',', '</r><r>') + '</r>' AS XML) AS States,
        CAST('<r>' + REPLACE(REPLACE(Products,'&','&amp;'), ',', '</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

DEMO