Эта хранимая процедура показывает ошибку подзапроса в SQL Server 2017 - PullRequest
0 голосов
/ 29 февраля 2020
ALTER PROCEDURE daily_routine
AS
BEGIN
    INSERT INTO temp_stats (i_count, r_count, s_count, w_count, n_count, z_count, t_count, 
                            p_hour, p_location, p_location_count, 
                            p_location_percentage, p_hour_percentage, d_date)
    VALUES (
       (SELECT SUM(i_count) as i_count FROM temp_h_stats),
       (SELECT SUM(r_count) as r_count FROM temp_h_stats),
       (SELECT SUM(s_count) as s_count FROM temp_h_stats),
       (SELECT SUM(w_count) as w_count FROM temp_h_stats),
       (SELECT SUM(n_count) as n_count FROM temp_h_stats),
       (SELECT SUM(z_count) as z_count FROM temp_h_stats),
       (SELECT SUM(t_count) as t_count FROM temp_h_stats),
       (SELECT time_range AS p_hour FROM temp_h_stats 
        WHERE t_count = (SELECT MAX(t_count) FROM temp_h_stats)),
       (SELECT p_location AS p_location FROM temp_hourly_stats 
        WHERE t_count = (SELECT MAX(t_count) FROM temp_hourly_stats)),
       (SELECT p_location_count AS p_location_count FROM temp_h_stats 
        WHERE p_location_count = (SELECT MAX(p_location_count) FROM temp_h_stats)),
       (SELECT MAX(p_location_percentage) AS p_location_percentage FROM temp_h_stats),
       (SELECT (MAX(t_count) * 100) / SUM(t_count) AS p_hour_percentage FROM temp_h_stats),
       (SELECT DATEADD(DD, -1,CURRENT_TIMESTAMP) AS recorded_date))
END

Результатом этого запроса является ошибка:

Подзапрос возвратил более 1 значения. Это недопустимо, когда подзапрос следует =,! =, <, <=,>,> = Или когда подзапрос используется в качестве выражения.

И я также реализовал ту же процедуру, что и эта один в SQL Server 2017 с тем же запросом, отличаются только имена таблиц, и он работает, но я не знаю, почему эта процедура не работает.

Ответы [ 2 ]

0 голосов
/ 29 февраля 2020

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

В следующем коде предполагается, что temp_hourly_stats действительно temp_h_stats. Код можно легко настроить для обработки двух разных таблиц, но имена выглядят очень похоже.

Я бы порекомендовал один запрос и оконные функции:

INSERT INTO temp_stats (i_count, r_count, s_count, w_count, n_count, z_count, t_count ,p_hour, p_location, p_location_count, p_location_percentage, p_hour_percentage, d_date)
    SELECT SUM(i_count) as i_count,
           SUM(r_count) as r_count,
           SUM(s_count) as s_count,
           SUM(w_count) as w_count,
           SUM(n_count) as n_count,
           SUM(z_count) as z_count
           SUM(t_count) as t_count,
           MAX(CASE WHEN seqnum_t_count = 1 THEN time_range END) as p_hour,
           MAX(CASE WHEN seqnum_t_count = 1 THEN p_location END) as p_location
           MAX(p_location_count) as p_location_count
           MAX(p_location_percentage) as p_location_percentage
           (MAX(t_count) * 100) / SUM(t_count) as p_hour_percentage
           DATEADD(day, -1, CURRENT_TIMESTAMP) as recorded_date)
    FROM (SELECT ths.*,
                 ROW_NUMBER() OVER (ORDER BY t_count DESC) as seqnum_t_count
          FROM temp_h_stats ths
         ) t;

Обратите внимание, что я упростил это logi c:

  (SELECT p_location_count AS p_location_count
   FROM temp_h_stats 
   WHERE p_location_count = (SELECT MAX(p_location_count) FROM temp_h_stats)
  ),

Кому:

MAX(p_location_count)
0 голосов
/ 29 февраля 2020

Что-то вроде этого должно быть лучше:

ALTER Procedure daily_routine
AS
BEGIN


DECLARE @MaxCounT_h_stats BIGINT
       ,@MaxCounT_hourly_states BIGINT
       ,@MaxLocation_Count BIGINT;

SET @MaxCounT_h_stats = (select max(t_count) from temp_h_stats);
SET @MaxCounT_hourly_states = (select max(t_count) from temp_hourly_stats);
SET @MaxLocation_Count = (select max(p_location_count) from temp_h_stats);

INSERT INTO temp_stats(i_count,r_count,s_count,w_count,n_count,z_count,t_count,p_hour,p_location,p_location_count,p_location_percentage,p_hour_percentage,d_date)
SELECT SUM(i_count) as i_count
      ,SUM(r_count) as r_count
      ,SUM(s_count) as s_count
      ,SUM(w_count) as w_count
      ,SUM(n_count) as n_count
      ,SUM(z_count) as z_count
      ,SUM(t_count) as t_count
      ,MAX(IIF(t_count = @MaxCounT_h_stats, time_range, NULL) as p_hour
      ,MAX(IIF(t_count = @MaxCounT_hourly_states, p_location, NULL) as p_location
      ,MAX(IIF(p_location_count = @MaxLocation_Count, p_location_count, NULL) as p_location_count
      ,MAX(p_location_percentage) as p_location_percentage
      ,(MAX(t_count)*100)/SUM(t_count) as p_hour_percentage
      ,DATEADD(DD, -1,CURRENT_TIMESTAMP) as recorded_date)
FROM temp_h_stats

END

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

(SELECT time_range as p_hour from temp_h_stats where t_count= (select max(t_count) from temp_h_stats)),
(SELECT p_location as p_location from temp_hourly_stats where t_count= (select max(t_count) from temp_hourly_stats)),
(SELECT p_location_count as p_location_count from temp_h_stats where p_location_count = (select max(p_location_count) from temp_h_stats)),

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

...