如何将我的N个小查询转换为一个查询?

时间:2019-06-18 15:16:38

标签: sql sql-server tsql

我有一个查询,该查询为我提供了给定日期和货币对的第一个可用值。

SELECT
    TOP 1 value
FROM
    my_table
WHERE
    date >= 'myinputdate'
    AND key = 'myinpukey'
ORDER BY date

我有N对键和日期,并且我尝试找出如何不一一查询每个对。桌子很大,N也很大,所以它又重又慢。

如何在一次查询中查询所有对?

4 个答案:

答案 0 :(得分:1)

一种解决方案是使用APPLY就像动态创建的“函数”,其中包含来自另一组的一个或多个列:

DECLARE @inputs TABLE (
    myinputdate DATE,
    myinputkey INT)

INSERT INTO @inputs(
    myinputdate,
    myinputkey)
VALUES
    ('2019-06-05', 1),
    ('2019-06-01', 2)

SELECT
    I.myinputdate,
    I.myinputkey,
    R.value
FROM
    @inputs AS I
    CROSS APPLY (
        SELECT TOP 1
            T.value
        FROM
            my_table AS T
        WHERE
            T.date >= I.myinputdate AND
            T.key = I.myinputkey
        ORDER BY
            T.date ) AS R

如果希望也显示OUTER APPLY结果值,则可以使用NULL。这支持获取多个列,并将ORDER BYTOP一起使用以控制行数。

答案 1 :(得分:1)

此解决方案没有变量。您可以通过为row_num谓词设置正确的值来控制 N

有很多方法可以满足您的需求,这取决于您的特定需求。正如它已经回答的那样,您可以使用temp / variable表存储这些条件,然后在使用谓词的相同条件下将其联接。您还可以创建用户定义的数据类型,并将其用作函数/过程的参数。您可以使用CROSS APPLY + VALUES子句来获取该列表,然后将其加入。

DROP TABLE IF EXISTS #temp;

CREATE TABLE #temp ( d DATE, k VARCHAR(100) );
GO

INSERT  INTO #temp
VALUES  ( '20180101', 'a' ),
        ( '20180102', 'b' ),
        ( '20180103', 'c' ),
        ( '20180104', 'd' ),
        ( '20190101', 'a' ),
        ( '20190102', 'b' ),
        ( '20180402', 'c' ),
        ( '20190103', 'c' ),
        ( '20190104', 'd' );

SELECT  a.d ,
        a.k
FROM    ( SELECT    d ,
                    k ,
                    ROW_NUMBER() OVER ( PARTITION BY k ORDER BY d DESC ) row_num
          FROM      #temp
          WHERE     (d >= '20180401'
                    AND k = 'a')
                    OR (d > '20180401'
                    AND k = 'b')
                    OR (d > '20180401'
                    AND k = 'c')
        ) a
WHERE   a.row_num <= 1;

-- VALUES way
SELECT  a.d ,
        a.k
FROM    ( SELECT    t.d ,
                    t.k ,
                    ROW_NUMBER() OVER ( PARTITION BY t.k ORDER BY t.d DESC ) row_num
          FROM      #temp t
          CROSS APPLY (VALUES('20180401','a'), ('20180401', 'b'), ('20180401', 'c')) f(d,k)
          WHERE t.d >= f.d AND f.k = t.k

        ) a
WHERE   a.row_num <= 1;

答案 2 :(得分:0)

如果所有键都使用相同的日期,则使用窗口功能:

SELECT key, value
FROM (SELECT t.*, ROW_NUMBER() OVER (PARTITION BY key ORDER BY date) as seqnum
      FROM my_table t
      WHERE date >= @input_date AND
            key IN ( . . . )
     ) t
WHERE seqnum = 1;

答案 3 :(得分:0)

       SELECT key, date,value
    FROM (SELECT ROW_NUMBER() OVER (PARTITION BY key,date ORDER BY date) as rownum,key,date,value
          FROM my_table
WHERE
    date >= 'myinputdate'


         ) as d
    WHERE d.rownum = 1;