Как я могу превратить мои маленькие запросы в один запрос? - PullRequest
0 голосов
/ 18 июня 2019

У меня есть запрос, который дает мне первое доступное значение для данной даты и пары.

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

У меня есть N пар ключей и дат, и я пытаюсь выяснить, как не запрашивать каждыйпара по одному.Таблица довольно большая, а также N, поэтому в настоящее время она тяжелая и медленная.

Как я могу запросить все пары в одном запросе?

Ответы [ 4 ]

1 голос
/ 19 июня 2019

Это решение без переменных.Вы управляете своим N , устанавливая правильное значение для предиката row_num.

Существует множество способов сделать то, что вы хотите, и все это зависит от ваших конкретных потребностей.Как уже было сказано, вы можете использовать таблицу 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;
1 голос
/ 18 июня 2019

Решение состоит в том, чтобы использовать 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 BY с TOP для управления количеством строк.

0 голосов
/ 18 июня 2019
       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;
0 голосов
/ 18 июня 2019

Если все ключи используют одну и ту же дату, используйте функции окна:

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...