如何选择与多个ID相关的各个行?

时间:2017-05-28 09:23:51

标签: sql-server tsql

我需要根据提供的ID列表从表中选择相关的ID - 实际上是邻接列表问题。我有一个单一Id的工作查询,但坦率地说,即使它工作,最好是优雅的!我欢迎有关改进的建议以及将单一Id解决方案转移到多Id解决方案的方法。

我有一个像这样的数据库表:

CREATE TABLE [BookingLines]
(
    [BookingLineId] BIGINT NOT NULL IDENTITY (138, 1),
    [BookingId] BIGINT NOT NULL,

    ---- Additional Columns Redacted for brevity

    [ContractNumber] INT NOT NULL DEFAULT 0,
    [ContractSubNumber] DECIMAL NOT NULL DEFAULT 0,

    ---- Additional Columns Redacted for brevity

);

此表中将有记录,在某些情况下,将有一对或多对与同一预订ID相关的记录。区别在ContractSubNumber列中,其中该对中的一个值为n.0,另一个值为n.1。因此,如果连续三对,则合同子编号将为:

LineId    BookingId     SubNumber
1          1            0.0
2          1            0.1
3          1            1.0
4          1            1.1
5          1            2.0
6          1            2.1

我可能需要从代表任一子编号的Line Id开始,然后收集相反的子编号。所以,如果我从LineId 1开始,我需要检索作为相关行的LineId 2。我可以使用多个子选择在单个Id上执行此操作,如下所示:

SELECT BookingLineId 
FROM
(
    SELECT BookingLineId 
    FROM   BookingLines
    WHERE  BookingId = 1 
    AND    FLOOR(ContractSubNumber) = 
    (
        SELECT FLOOR(ContractSubNumber) 
        FROM   BookingLines 
        WHERE  BookingId = 1 AND BookingLineId = (1)
    )
)
WHERE BookingLineId <> 1; 

这样可以正常工作,在这种情况下返回值2.

  1. 如何让这更优雅高效?
  2. 如何重写此选项以返回指定列表中所有ID的相反值,例如

    在哪里BookingId = 1和BookingLineId IN(1,3,5))

  3. 让它返回结果2,4,6?

    感谢所有建议。

    修改

    我已经纠正了原始问题中提供的SQL中的拼写错误,并且使用了@McNets提出的框架,这是我选择的解决方案:

    SELECT BL.BookingLineId 
    FROM BookingLines BL
    INNER JOIN BookingLines ABL ON ABL.BookingId = BL.BookingId
    AND ABL.BookingLineId IN (22, 24, 26)
    AND FLOOR(BL.ContractSubNumber) = FLOOR(ABL.ContractSubNumber)
    WHERE BL.BookingId = 3 AND BL.BookingLineId NOT IN (22,24,26);
    

    我非常感谢这些贡献和最终答案。谢谢你们!

2 个答案:

答案 0 :(得分:0)

它的子编号总是* .0&amp; * 0.1。然后你可以试试下面的

SELECT oppo.* 
FROM AgencyBookingLines AS main
INNER JOIN AgencyBookingLines AS oppo ON 
oppo.BookingId = main.BookingId
AND oppo.SubNumber <> main.SubNumber
AND FLOOR(oppo.SubNumber) = FLOOR(main.SubNumber)
WHERE main.BookingId = 1
      AND main.LineId IN (1,3,5)

答案 1 :(得分:0)

如果没有关于AgencyBookingLines的信息且没有样本数据,我无法设置fiddle示例,但我认为您可以将AgencyBookingLines子查询移动到ON子句。

SELECT     BL.BookingLineId 
FROM       BookingLines BL
INNER JOIN AgencyBookingLines ABL
ON         ABL.BookingId = BL.BookinId
AND        ABL.BookingLineId = 1
AND        FLOOR(BL.ContractSubNumber) = FLOOR(ABL.ContractSubNumber
WHERE      BL.BookingId = 1
AND        BL.BookingLineId <> 1;
--
-- AND     BL.BookingLineId IN (2,4,6);