如何在两个参数的基础上连接两个以上的表?

时间:2015-01-15 06:38:14

标签: sql sql-server sql-server-2008 join

我有三个表#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
tbVendorAgent Id字段的基础上分配了States

对于E.g我已使用Products NamesIds New york获取所有AgentId = 1ProductId 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包含@AgentId1包含{{1}}。

3 个答案:

答案 0 :(得分:0)

尝试这个:

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

答案 1 :(得分:0)

将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...

现在,您将使用statesProductIdProductName

获取所有AgentId

enter image description here

答案 2 :(得分:0)

写为:

;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