:: Visual Foxpro, Foxpro for DOS
Помогите с SQL запросом
ZenTigra

Сообщений: 514
Дата регистрации: 03.12.2004
Помогите написать SQL-запрос.
Дело в том, что во второй таблице ОЧЕНЬ много записей, тому необходима оптимизация, индексы по Key и Date есть.

Вот простой пример. Есть две таблицы

Справочник товара: goods
Key Name Kod
1 Товар1 1
2 Товар2 2
3 Товар3 1

и таблица прихода: table1
Key Date Kol
3 12.2017 3.000
1 01.2018 10.000
2 02.2018 6.000
1 02.2018 5.000

Необходимо отобразить весь товар с кодом - 1, и датой больше 31.12.2017
Чтоб получилось вот так.
Key Name Suma1 Suma2
1 Товар1 10.000 5.000
3 Товар3 0.000 (или Null)

PS.Проблема только в оптимизации SQL запроса.
SELECT Goods.Key Goods.Name Goods.Kod,;
SUM(IIF(table1.date=01.2018,table1.Kol,000000.000) AS suma1,;
SUM(IIF(table1.date=02.2018,table1.Kol,000000.000) AS suma2,;
SUM(IIF(table1.date=03.2018,table1.Kol,000000.000) AS suma3,;
SUM(IIF(table1.date=04.2018,table1.Kol,000000.000) AS suma4,;
SUM(IIF(table1.date=05.2018,table1.Kol,000000.000) AS suma5,;
SUM(IIF(table1.date=06.2018,table1.Kol,000000.000) AS suma6,;
SUM(IIF(table1.date=07.2018,table1.Kol,000000.000) AS suma7,;
SUM(IIF(table1.date=08.2018,table1.Kol,000000.000) AS suma8,;
SUM(IIF(table1.date=09.2018,table1.Kol,000000.000) AS suma9,;
SUM(IIF(table1.date=10.2018,table1.Kol,000000.000) AS suma10,;
SUM(IIF(table1.date=11.2018,table1.Kol,000000.000) AS suma11,;
SUM(IIF(table1.date=12.2018,table1.Kol,000000.000) AS suma12;
FROM goods LEFT OUTER JOIN table1;
ON Goods.key = table1.key;
WHERE goods.kod=1;
ORDER BY goods.key;
GROUP BY goods.key;
INTO CURSOR SQL1



Исправлено 2 раз(а). Последнее : ZenTigra, 09.03.18 11:46
Ratings: 0 negative/0 positive
Re: Помогите с SQL запросом
AndyNigmatec
Автор

Сообщений: 1573
Откуда: Волгоград
Дата регистрации: 28.06.2015
ZenTigra
Необходимо отобразить весь товар с кодом - 1, и датой больше 31.12.2017

SELECT 0
CREATE CURSOR cTovar (Key i, Name c(80), Kod i)
INSERT INTO cTovar (Key, Name, Kod) VALUES (1, 'Товар1', 1)
INSERT INTO cTovar (Key, Name, Kod) VALUES (2, 'Товар2', 2)
INSERT INTO cTovar (Key, Name, Kod) VALUES (3, 'Товар3', 1)
SELECT 0
CREATE CURSOR cTable1 (Key i, pDate d, Kol i)
INSERT INTO cTable1 (Key, pDate, Kol) VALUES (3, {^2017-12-01}, 3)
INSERT INTO cTable1 (Key, pDate, Kol) VALUES (1, {^2018-01-01}, 10)
INSERT INTO cTable1 (Key, pDate, Kol) VALUES (2, {^2018-02-01}, 6)
INSERT INTO cTable1 (Key, pDate, Kol) VALUES (1, {^2018-02-04}, 5)
lcDate={^2017-12-31}
SELECT b.key, MAX(b.name) as name, SUM(a.kol) as nsum;
FROM cTable1 a JOIN cTovar b ON a.key=b.key;
WHERE b.kod=1 AND a.pdate>lcDate;
INTO CURSOR c1 READWRITE;
GROUP BY b.key

в предположении что Key в cTovar уникален



Исправлено 1 раз(а). Последнее : AndyNigmatec, 09.03.18 12:28
Ratings: 0 negative/0 positive
Re: Помогите с SQL запросом
AndyNigmatec
Автор

Сообщений: 1573
Откуда: Волгоград
Дата регистрации: 28.06.2015
или же (если я прально понял задачу) так:

SELECT 0
CREATE CURSOR cTovar (Key i, Name c(80), Kod i)
INSERT INTO cTovar (Key, Name, Kod) VALUES (1, 'Товар1', 1)
INSERT INTO cTovar (Key, Name, Kod) VALUES (2, 'Товар2', 2)
INSERT INTO cTovar (Key, Name, Kod) VALUES (3, 'Товар3', 1)
SELECT 0
CREATE CURSOR cTable1 (Key i, pDate d, Kol i)
INSERT INTO cTable1 (Key, pDate, Kol) VALUES (3, {^2017-12-01}, 3)
INSERT INTO cTable1 (Key, pDate, Kol) VALUES (1, {^2018-01-01}, 10)
INSERT INTO cTable1 (Key, pDate, Kol) VALUES (2, {^2018-02-01}, 6)
INSERT INTO cTable1 (Key, pDate, Kol) VALUES (1, {^2018-02-04}, 5)
lcDate={^2015-12-31}
SELECT a1.key, a1.name, a1.kod, a.nsum;
FROM cTovar a1;
LEFT JOIN (;
select b.key, SUM(b.kol) as nsum from cTable1 b where b.pdate>lcDate group by b.key;
) a ON a1.key=a.key;
WHERE a1.kod=1

P.S. догнал - я все не прально понял, у ТС все готово оказывается



Исправлено 1 раз(а). Последнее : AndyNigmatec, 09.03.18 12:42
Ratings: 0 negative/0 positive
Re: Помогите с SQL запросом
ZenTigra

Сообщений: 514
Дата регистрации: 03.12.2004
Не подходит, мне нужно чтоб показало ВЕСЬ товар с кодом kod=1, а в этом запросе отображается только товар в которого есть движение в 2018 году.

Нужно чтоб было вот так:
Key Name Suma1 Suma2
1 Товар1 10.000 5.000
3 Товар3 0.000 (или Null)
Ratings: 0 negative/0 positive
Re: Помогите с SQL запросом
AndyNigmatec
Автор

Сообщений: 1573
Откуда: Волгоград
Дата регистрации: 28.06.2015
ZenTigra
Не подходит, мне нужно чтоб показало ВЕСЬ товар с кодом kod=1
- второй вариант и показывает весь ))), но я так понял вам не нужна тупа сумма - а она должна быть разбита по месяцам (исходя из приведенного запроса)


Исправлено 1 раз(а). Последнее : AndyNigmatec, 09.03.18 12:44
Ratings: 0 negative/0 positive
Re: Помогите с SQL запросом
ZenTigra

Сообщений: 514
Дата регистрации: 03.12.2004
Второй вариант, то что нужно, спасибо. Буду пробовать на производительность.

PS.Это формирование закупочного листа, со статистикой продаж по месяцах, и иной дополнительной информацией.
Я не стал показывать настоящий код, он сложный.
Ratings: 0 negative/0 positive
Re: Помогите с SQL запросом
AndyNigmatec
Автор

Сообщений: 1573
Откуда: Волгоград
Дата регистрации: 28.06.2015
Да детали не суть ))) ... но боюсь оптимизировать тут особо не получится ... поскоку в таблице прихода table1 нету кода и его полюбому подтягивать из справочника



Исправлено 1 раз(а). Последнее : AndyNigmatec, 09.03.18 13:07
Ratings: 0 negative/0 positive
Re: Помогите с SQL запросом
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
CREATE CURSOR goods (KEY i, NAME c(80), Kod i)
INSERT INTO goods (KEY, NAME, Kod) VALUES (1, 'Товар1', 1)
INSERT INTO goods (KEY, NAME, Kod) VALUES (2, 'Товар2', 2)
INSERT INTO goods (KEY, NAME, Kod) VALUES (3, 'Товар3', 1)
INDEX ON KEY TAG KEY CANDIDATE
INDEX ON Kod TAG Kod
CREATE CURSOR Table1 (KEY i, DATE d, Kol B(3))
INSERT INTO Table1 (KEY, DATE, Kol) VALUES (3, {^2017-12-01}, 3)
INSERT INTO Table1 (KEY, DATE, Kol) VALUES (1, {^2018-01-01}, 10)
INSERT INTO Table1 (KEY, DATE, Kol) VALUES (2, {^2018-02-01}, 6)
INSERT INTO Table1 (KEY, DATE, Kol) VALUES (1, {^2018-02-04}, 5)
INDEX ON KEY TAG KEY
INDEX ON DATE TAG DATE
SYS(3054,12)
LOCAL lnYear, lnKod
lnYear = 2018
lnKod = 1
SELECT goods.KEY, goods.NAME, goods.Kod,;
CAST(SUM(IIF(MONTH(Table1.DATE)=1, Table1.Kol, 0)) AS B(3)) AS suma1, ;
CAST(SUM(IIF(MONTH(Table1.DATE)=2, Table1.Kol, 0)) AS B(3)) AS suma2, ;
CAST(SUM(IIF(MONTH(Table1.DATE)=12, Table1.Kol, 0)) AS B(3)) AS suma12 ;
FROM goods LEFT OUTER JOIN Table1 ;
ON goods.KEY = Table1.KEY AND ;
Table1.DATE BETWEEN DATE(m.lnYear, 1, 1) AND DATE(m.lnYear, 12, 31) ;
WHERE goods.Kod = m.lnKod ;
ORDER BY goods.KEY ;
GROUP BY goods.KEY, goods.NAME, goods.Kod ;
INTO CURSOR SQL1
BROWSE

Как-то так. Если ограничивать "большую таблицу" нужно именно в рамках одного года (иначе большого смысла в подсчёте "помесячных сумм" не видно).

На будущее - самому неплохо бы приводить нужные create cursor/table. А если речь про "большие объёмы" и оптимизацию, то и с FOR циклом генерящим нужные 100500 записей для "тяжёлых" таблиц.

P.S. В зависимости от количества разных "товаров" и "товаров внутри искомой группы", и количества лет в table1 (если там история за последние 50 лет, это совсем не одно и то же что история за 2-3 года) может оказаться выгоднее считать отдельно (подзапросом) помесячные суммы по ВСЕМ товарам нужного года, а потом уже этот подзапрос прицеплять к таблице товаров, попутно фильтруя по "коду группы".


------------------
WBR, Igor




Исправлено 1 раз(а). Последнее : Igor Korolyov, 09.03.18 13:47
Ratings: 0 negative/0 positive
Re: Помогите с SQL запросом
ZenTigra

Сообщений: 514
Дата регистрации: 03.12.2004

На жаль, попытки оптимизировать SQL запрос не привили к желаемому результату.
Мой первый SQL запрос работает быстрее на ~30%
Все таки он больше отсекает ненужных записей.

PS.Не видя структуру базы данных, и ее записей, трудно подсказать как оптимизировать запрос.

Сейчас, попробую разобраться с кодом от Igor Korolyov...



Исправлено 1 раз(а). Последнее : ZenTigra, 09.03.18 14:17
Ratings: 0 negative/0 positive
Re: Помогите с SQL запросом
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Надеюсь у тебя в поле даты не записано на самом деле дробное число вида MM.YYYY - иначе извини, но адекватной оптимизации тебе не видать как своих ушей А "придумщику" такого способа хранения даты (пусть даже только года и месяца) стоит глаз на ж*пу натянуть


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Помогите с SQL запросом
ZenTigra

Сообщений: 514
Дата регистрации: 03.12.2004
Та нет, то я так написал, чтоб кода в примере меньше было...
Ratings: 0 negative/0 positive
Re: Помогите с SQL запросом
AndyNigmatec
Автор

Сообщений: 1573
Откуда: Волгоград
Дата регистрации: 28.06.2015
да все мы писали ... чего уж ))) но есть куда смотреть/расти
Ratings: 0 negative/0 positive
Re: Помогите с SQL запросом
AndyNigmatec
Автор

Сообщений: 1573
Откуда: Волгоград
Дата регистрации: 28.06.2015
и еще, (пардон за 100500-ый повтор) ежели данных реально много - может есть резон таки перейтить на каку-либо СУБД "повзрослее" оставив "на пока" клиента на фоксе? Уверяю, очень многое станет куда проще (и быстрее) несмотря на кажущийся монструозным объем переделок в коде клиента ... ну если конечно он не совсем через жопу написен
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 18 Sejko  (Гостей: 17)

© 2000-2024 Fox Club 
Яндекс.Метрика