Проблема с таблицей соединения SQL «один ко многим»

У меня есть 2 таблицы, которые являются отношениями один ко многим. Я хочу объединить обе таблицы, но результат, показанный после объединения, не тот, который мне нужен. Ниже представлена ​​таблица и примеры данных.

Create table #temp (
    DONo varchar(10),
    Amount decimal(18,2),
    OrderNo varchar(10)
)

Create table #order (
    Item varchar(10),
    Amount decimal(18,2),
    OrderNo varchar(10),
    PackingDate date
)

Insert into #temp(DONo, Amount, OrderNo)
VALUES('A123', 1000, 'O123')
Insert into #temp(DONo, Amount, OrderNo)
VALUES('A124', 1100, 'O124')

Insert into #order (OrderNo, Item, Amount, PackingDate)
VALUES('O123', 'Pen', 100, '2024-02-01')
Insert into #order (OrderNo, Item, Amount, PackingDate)
VALUES ('O123', 'Color', 800, '2024-02-01')
Insert into #order (OrderNo, Item, Amount, PackingDate)
VALUES ('O123', 'Box', 100, '2024-02-02')

Я попробовал ниже запрос на соединение

select 
   do.DONo, do. Amount, do.OrderNo, SUM(so.Amount)[[OrderAmount], so.PackingDate 
from #temp do
left join
  #order so
on
  do.OrderNo = so.OrderNo
group by
  do.DONo, do. Amount, do.OrderNo, so.PackingDate

Вот результат приведенного выше запроса

DONo    DOAmount  OrderNo   Amount     PackingDate
A123    1000.00   O123     900.00     2024-02-01
A123    1000.00   O123     100.00     2024-02-02
A124    1100.00   O124      NULL      NULL

Ожидаемый результат, который я хочу, как показано ниже

DONo    DOAmount  OrderNo   Amount     PackingDate
A123    1000.00   O123     900.00     2024-02-01
A123              O123     100.00     2024-02-02
A124    1100.00   O124      NULL      NULL

Поскольку номер DO одинаков для заказа O123, сумму DO мне нужно указать один раз. Причина, по которой мне нужно показать количество DO один раз, заключается в том, что при визуализации инструменты просуммируют количество DO, и на гистограмме оно увеличится вдвое.

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

Что означает пробел? Это не NULL, как вы явно указываете значения NULL, но это также не может быть строка нулевой длины, поскольку DOAmount явно является числовым типом. Хотя, похоже, вам просто нужно проверить значение ROW_NUMBER и изменить значение, если оно не 1.

Thom A 04.06.2024 10:04

Это похоже на проблему X/Y. «потому что при визуализации инструменты суммируют сумму DO» — Можете ли вы изменить их, чтобы этого не делать? Вместо суммирования они могут сделать что-то еще, например. выбрать самый большой? Какие инструменты вы используете?

Alex 04.06.2024 10:08

@ThomA, спасибо, что указал мне направление. Теперь это работа.

Bubble Bub 04.06.2024 10:35
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
4
70
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Однако, если вы не можете найти способ, позволяющий инструменту визуализации игнорировать несколько значений одного и того же DONo, все равно есть способ обработать это в чистом T-SQL, используя RowNumber и общее табличное выражение:

;WITH CTE AS 
(
select 
   do.DONo, do.Amount, do.OrderNo, SUM(so.Amount)[OrderAmount], so.PackingDate, 
   ROW_NUMBER() OVER (PARTITION BY do.DONo ORDER BY so.PackingDate) As RN
from #temp do
left join
  #order so
on
  do.OrderNo = so.OrderNo
group by
  do.DONo, do. Amount, do.OrderNo, so.PackingDate
)

SELECT DONo, IIF(RN = 1, Amount, NULL) As Amount, OrderNo, OrderAmount, PackingDate
FROM CTE
ORDER BY DONo, PackingDate;

Примечание. Символ точки с запятой (;) является символом-терминатором.
На самом деле он не стоит перед ключевым словом WITH, однако, поскольку в T-SQL он обычно необязателен (если только следующий оператор не является общим табличным выражением), общепринятой практикой является начало общих табличных выражений с точки с запятой перед ключевым словом WITH.

Я не думаю, что CTE здесь вообще нужен, посмотрите это демо

GuidoG 04.06.2024 10:14

@GuidoG Я согласен, так лучше. хотите опубликовать в качестве ответа или отредактировать это в этом?

Zohar Peled 04.06.2024 10:22

я это написал в ответе

GuidoG 04.06.2024 10:27
Ответ принят как подходящий

просто замените

do.Amount,

этим

 case when row_number() over (partition by do.DONo order by do.DONo) = 1 then do.Amount else null end as Amount,

полный запрос

select do.DONo, 
       case when row_number() over (partition by do.DONo order by do.DONo) = 1 then do.Amount else null end as Amount,
       do.OrderNo, 
       sum(so.Amount)OrderAmount, 
       so.PackingDate 
from temp do
  left join orders so on do.OrderNo = so.OrderNo
group by
  do.DONo, do. Amount, do.OrderNo, so.PackingDate

результат

DOНет Количество № заказа Сумма заказа Дата упаковки А123 1000,00 О123 900.00 2024-02-01 А123 нулевой О123 100.00 2024-02-02 А124 1100.00 О124 нулевой нулевой

Посмотрите это демо

Другие вопросы по теме