SQL LEFT JOIN在三个表上有条件

时间:2017-07-12 13:59:20

标签: sql sql-server left-join

我想从三个表中获取信息,如:

项目

itemId  Name   Quantity Price  
1       Pen    100      1,0
2       Pencil 100      0,5
3       Glue   20       1,5

ItemFiles

itemId fileId
1      1001
1      1002
1      1003
2      2001
3      3001
3      3002

phisicsFile

fileId Filename 
1001   order_101_20170621.pdf
1002   delivery_404_20170627.pdf
1003   payement_20170630.pdf
2001   order_102_20170623.pdf
3001   order_103_20170624.pdf
3002   delivery_404_20170627.pdf

我需要一个像这样的结果的单一查询

Name    Quantity    Price     Order Delivery   Payed
Pen         100       1,0      True   True    True

Pencil      100       0,5      True   False   False

Glue         20       1,5      True   True    False

我尝试这样的事情

SELECT
     I.itemId                           AS Id,
    CASE 
            WHEN FS.Filename like '%'Order'%' THEN 'True' 
            ELSE 'False' 
    END                                                        AS Order


FROM       Item  I

 left join 
ItemFiles on I.itemId = IF.itemId
left join phisicsFile PF on (IF.file_id = PF.fileId AND PF.Filename like '%order%')

WHERE  I.itemId= @itemId

但是我在结果中得到重复的行

4 个答案:

答案 0 :(得分:2)

您不需要LEFT JOIN,只需加入GROUP BY即可。然后使用条件计数来检查每种文件类型的存在。

<强> SQL DEMO

SELECT I.[itemId], I.[Name], I.[Quantity], I.[Price],
       CAST( COUNT(CASE WHEN P.Filename like '%order%' THEN 1 END) as bit) as [Orders],
       CAST( COUNT(CASE WHEN P.Filename like '%delivery%' THEN 1 END) as bit) as [Delivery],
       CAST( COUNT(CASE WHEN P.Filename like '%payement%' THEN 1 END) as bit) as [Payment]
FROM Items I
JOIN ItemFiles  F
  ON I.[itemId] = F.[itemId]
JOIN phisicsFile P
  ON F.[fileId] = P.[fileId]
GROUP BY   I.[itemId], I.[Name], I.[Quantity], I.[Price]

<强>输出

enter image description here

答案 1 :(得分:1)

这是另一种选择......

IF OBJECT_ID('tempdb..#Item', 'U') IS NOT NULL 
DROP TABLE #Item;

CREATE TABLE #Item (
    ItemId INT NOT NULL PRIMARY KEY CLUSTERED,
    Name VARCHAR(20) NOT NULL,
    Quantity INT NOT NULL,
    Price MONEY NOT NULL 
    );
INSERT #Item (ItemId, Name, Quantity, Price) VALUES 
(1, 'Pen', 100, 1.0),
(2, 'Pencil', 100, 0.5),
(3, 'Glue', 20, 1.5);

IF OBJECT_ID('tempdb..#ItemFiles', 'U') IS NOT NULL 
DROP TABLE #ItemFiles;

CREATE TABLE #ItemFiles (
    ItemId INT NOT NULL,
    FileId INT NOT NULL,
    PRIMARY KEY CLUSTERED (ItemId, FileId)
    );
INSERT #ItemFiles (ItemId, FileId) VALUES
(1, 1001),
(1, 1002),
(1, 1003),
(2, 2001),
(3, 3001),
(3, 3002);

IF OBJECT_ID('tempdb..#PhisicsFile', 'U') IS NOT NULL 
DROP TABLE #PhisicsFile;

CREATE TABLE #PhisicsFile (
    FieldId INT NOT NULL PRIMARY KEY CLUSTERED,
    FileName VARCHAR(50) NOT NULL 
    );
INSERT #PhisicsFile (FieldId, FileName) VALUES
(1001, 'order_101_20170621.pdf'),
(1002, 'delivery_404_20170627.pdf'),
(1003, 'payement_20170630.pdf'),
(2001, 'order_102_20170623.pdf'),
(3001, 'order_103_20170624.pdf'),
(3002, 'delivery_404_20170627.pdf');

--=================================================

SELECT 
    i.ItemId,
    i.Name,
    i.Quantity,
    i.Price,
    [Order] = CASE WHEN xif.HasOrder = 1 THEN 'True' ELSE 'False' END,
    Delivery = CASE WHEN xif.HasDelivery = 1 THEN 'True' ELSE 'False' END,
    Payement = CASE WHEN xif.HasPayement = 1 THEN 'True' ELSE 'False'END
FROM 
    #Item i
    OUTER APPLY (
        SELECT 
            HasOrder = MAX(CASE WHEN pf.FileName LIKE 'order%' THEN 1 END),
            HasDelivery = MAX(CASE WHEN pf.FileName LIKE 'delivery%' THEN 1 END),
            HasPayement = MAX(CASE WHEN pf.FileName LIKE 'payement%' THEN 1 END)
        FROM 
            #ItemFiles ifi
            JOIN #PhisicsFile pf
                ON ifi.FileId = pf.FieldId
        WHERE 
            i.ItemId = ifi.ItemId
        ) xif;

HTH, 杰森

答案 2 :(得分:0)

select Id,Name,Quantity,Price,
    case when [order] = 1 then 'true' else 'false' end as [order],
    case when [delivery]=1 then 'true' else 'false' end as [delivery],
    case when [payement]=1 then 'true' else 'false' end as [payement]
from 
(SELECT
     I.itemId AS Id,
     I.Name,
     I.Quantity,
     I.Price,
     SUBSTRING(PF.Filename,0,charindex('_',PF.Filename))  stat                               
FROM       #Item  I
INNER join #ItemFiles Itf on I.itemId = Itf.itemId
INNER join #phisicsFile PF on Itf.fileId = PF.fileId) as s
PIVOT
(
count(stat) for stat IN ([order],[delivery],[payement])
) as p

如果您使用的是sql 2016,则可以使用STRING_SPLIT(字符串,分隔符)代替子字符串。

答案 3 :(得分:0)

onCreate()