Сохранение только отдельных строк во временной таблице - PullRequest
0 голосов
/ 25 января 2019

У меня есть запрос, в котором я хочу получить сумму затрат, найденную в #temp_costs, и хочу сгруппировать их по version_id (чтобы узнать, каковы общие затраты компании) Общая стоимость рассчитывается вместе с определенным типом затрат, где столбец is_included равен 0 или 1. #temp_costs_count - это ранее созданная таблица.

Однако, поскольку следующий запрос выполняется в цикле (я не могу вынуть его из цикла). Скажем, он зацикливается на 4 компании, в результате получается список, похожий на:

What it looks like right now

И вот как это желательно должно выглядеть

What it should look like

Это мой код прямо сейчас

  insert into  #temp_costs_count (
    version_id,
    total_costs,
    cost_included
    )

        select  version_id,
                count(*),
                sum(case when is_included = 1 then 1 else 0 end)
        from #temp_costs
        group by version_id

        select * 
        from #temp_costs_count

Я получаю желаемый результат, запустив

select distinct * 
from #temp_costs_count

Однако есть ли способ, которым я могу использовать оператор обновления, чтобы он также сохранялся в #temp_costs_count?

Ответы [ 4 ]

0 голосов
/ 25 января 2019

Я пропустил, зачем вам это нужно, и просто посмотрел на другие ответы - но поскольку кажется, что намерение состоит в том, чтобы пропустить вставку уже существующих строк, вы можете добиться этого, добавив следующее в таблицу #temp.

CREATE UNIQUE INDEX ix
  ON #temp_costs_count(version_id, total_costs, cost_included)
  WITH (IGNORE_DUP_KEY = ON); 

тогда любые дубликаты будут эффективно идентифицироваться и игнорироваться без необходимости изменения запроса

0 голосов
/ 25 января 2019

Вы можете использовать подзапрос с отдельным:

insert into  #temp_costs_count (
version_id,
total_costs,
cost_included
)
select distinct version_id,total_costs,cost_included from (
    select  version_id,
            count(*) as total_costs,
            sum(case when is_included = 1 then 1 else 0 end) as cost_included
    from #temp_costs
    group by version_id

). as q
0 голосов
/ 25 января 2019

Вы можете использовать EXCEPT только для вставки записей, которые еще не существуют в вашей таблице. например:

INSERT #temp_costs_count (version_id, total_costs, cost_included)
SELECT  version_id,
        count(*),
        sum(case when is_included = 1 then 1 else 0 end)
FROM    #temp_costs
GROUP BY version_id
EXCEPT
SELECT version_id, total_costs, cost_included
FROM    #temp_costs_count;

Или, если вы определяете дубликат по-другому (например, просто запись с этим конкретным version_id), тогда вы можете использовать NOT EXISTS например ::

INSERT #temp_costs_count (version_id, total_costs, cost_included)
SELECT version_id,
        count(*),
        sum(case when is_included = 1 then 1 else 0 end)
FROM    #temp_costs AS tc
WHERE NOT EXISTS (SELECT 1 FROM temp_costs_count AS tcc WHERE tcc.version_id = tc.version_id)
GROUP BY version_id;

Кроме того, я, вероятно, могу, с одной стороны, посчитать, сколько раз у меня было , чтобы использовать цикл в SQL Server (и я тратил почти каждый рабочий день за последние 12 лет написание SQL). По моему опыту, примерно в 99,9% случаев, когда кто-то считает, что ему нужно использовать цикл, он этого не делает, и существует гораздо более эффективное решение на основе множеств.

0 голосов
/ 25 января 2019

Вы можете проверить отсутствие записи в предложении HAVING, используя NOT EXISTS и коррелированный подзапрос. То есть запись не выбрана и, следовательно, вставлена, когда она уже существует.

INSERT INTO #temp_costs_count
            (version_id,
             total_costs,
             cost_included)
            SELECT tc.version_id,
                   count(*),
                   sum(CASE
                         WHEN tc.is_included = 1 THEN
                           1
                         ELSE
                           0
                       END)
                   FROM #temp_costs tc
                   GROUP BY tc.version_id
                   HAVING NOT EXISTS (SELECT *
                                             FROM #temp_costs_count tcc
                                             WHERE tcc.version_id = version_id
                                                   AND tcc.total_costs = count(*)
                                                   AND tcc.cost_included = sum(CASE
                                                                                 WHEN tc.is_included = 1 THEN
                                                                                   1
                                                                                 ELSE
                                                                                   0
                                                                               END));
...