В поисках оптимизации запросов SQL для ускорения загрузки страницы за 20 секунд.Мы должны уменьшить количество запросов, которые мы имеем.Тезисы - это текущие запросы:
SELECT
P.[Starting Date] as current_promo
FROM [Sales Price] P
WHERE P.[Item No_] = :id
AND P.[Ending Date] >= getdate()
AND P.[Starting Date] <= getdate()
ORDER BY P.[Starting Date] ASC;
SELECT
P.[Starting Date] as current_promo
FROM [Purchase Line Discount] P
WHERE P.[Item No_] = :id
AND (P.[Line Discount_] > 0 OR P.[Line Discount_2] > 0)
AND (P.[Ending Date] >= getdate() OR P.[Ending Date] = '1753-01-01 00:00:00.000')
AND (P.[Starting Date] <= getdate() OR P.[Starting Date] = '1753-01-01 00:00:00.000')
ORDER BY P.[Starting Date] ASC;
SELECT
P.[Lot Quantity] as lot,
P.[Free Quantity] as free
FROM [Purchase Price] P
WHERE P.[Item No_] = :id
AND (P.[Ending Date] >= getdate() OR P.[Ending Date] = '1753-01-01 00:00:00.000')
AND (P.[Starting Date] <= getdate() OR P.[Starting Date] = '1753-01-01 00:00:00.000')
ORDER BY P.[Ending Date] ASC;
SELECT
P.[Starting Date] as next_promo
FROM [Purchase Price] P
WHERE P.[Item No_] = :id
AND P.[Minimum Quantity] = 1
AND P.[Ending Date] > P.[Starting Date]
AND P.[Starting Date] > getdate()
ORDER BY P.[Starting Date] ASC;
Нам нужен только первый результат каждого запроса.Хорошо, я могу сделать TOP 1
, никаких проблем с этим.Но мне все еще нужно объединить эти 4 запроса.Вот один из моих проектов:
SELECT
sales_promo,
purchase_promo,
lot, free,
next_promo
FROM
(
SELECT TOP 1 P.[Starting Date] as sales_promo
FROM [Purchase Line Discount] P
WHERE P.[Item No_] = :id
AND (P.[Line Discount _] > 0 OR P.[Line Discount _ 2] > 0)
AND (P.[Ending Date] >= getdate() OR P.[Ending Date] = '1753-01-01 00:00:00.000')
AND (P.[Starting Date] <= getdate() OR P.[Starting Date] = '1753-01-01 00:00:00.000')
ORDER BY P.[Starting Date] ASC
) salesPromo FULL OUTER JOIN
(
SELECT TOP 1 P.[Starting Date] as purchase_promo
FROM [Purchase Line Discount] P
WHERE P.[Item No_] = :id
AND (P.[Line Discount _] > 0 OR P.[Line Discount _ 2] > 0)
AND (P.[Ending Date] >= getdate() OR P.[Ending Date] = '1753-01-01 00:00:00.000')
AND (P.[Starting Date] <= getdate() OR P.[Starting Date] = '1753-01-01 00:00:00.000')
ORDER BY P.[Starting Date] ASC
) purchasePromo ON 1=1 FULL OUTER JOIN
(
SELECT TOP 1 P.[Lot Quantity] as lot, P.[Free Quantity] as free
FROM [Purchase Price] P
WHERE P.[Item No_] = :id
AND (P.[Ending Date] >= getdate() OR P.[Ending Date] = '1753-01-01 00:00:00.000')
AND (P.[Starting Date] <= getdate() OR P.[Starting Date] = '1753-01-01 00:00:00.000')
ORDER BY P.[Ending Date] ASC
) lotandfee ON 1=1 FULL OUTER JOIN
(
SELECT TOP 1 P.[Starting Date] as next_promo
FROM [Purchase Price] P
WHERE P.[Item No_] = :id
AND P.[Minimum Quantity] = 1
AND P.[Ending Date] > P.[Starting Date]
AND P.[Starting Date] > getdate()
ORDER BY P.[Starting Date] ASC
) nextPromo ON 1=1
Отлично, это работает!
Вопрос :
По некоторым подзапросам у меня есть0 результатов.Когда я делаю этот запрос непосредственно в базе данных, у меня нет проблем, null
, когда у меня нет результата для подзапроса и результата для второго подзапроса.Но когда я делаю это с PDO, всякий раз, когда у меня есть подзапрос с 0 результатом, я заканчиваю тем, что вся строка исчезает!
Вот еще один черновик, дающий тот же результат:
SELECT
sales_promo
purchase_promo,
lot, free,
next_promo
FROM
(
SELECT q.* FROM (SELECT NULL) AS d (dummy) LEFT JOIN (
SELECT TOP 1 P.[Starting Date] as sales_promo
FROM [Purchase Line Discount] P
WHERE P.[Item No_] = :id
AND (P.[Line Discount _] > 0 OR P.[Line Discount _ 2] > 0)
AND (P.[Ending Date] >= getdate() OR P.[Ending Date] = '1753-01-01 00:00:00.000')
AND (P.[Starting Date] <= getdate() OR P.[Starting Date] = '1753-01-01 00:00:00.000')
ORDER BY P.[Starting Date] ASC
) AS q ON 1=1
) salesPromo,
(
SELECT q.* FROM (SELECT NULL) AS d (dummy) LEFT JOIN (
SELECT TOP 1 P.[Starting Date] as purchase_promo
FROM [Purchase Line Discount] P
WHERE P.[Item No_] = :id
AND (P.[Line Discount _] > 0 OR P.[Line Discount _ 2] > 0)
AND (P.[Ending Date] >= getdate() OR P.[Ending Date] = '1753-01-01 00:00:00.000')
AND (P.[Starting Date] <= getdate() OR P.[Starting Date] = '1753-01-01 00:00:00.000')
ORDER BY P.[Starting Date] ASC
) AS q ON 1=1
) purchasePromo,
(
SELECT q.* FROM (SELECT NULL) AS d (dummy) LEFT JOIN (
SELECT TOP 1 P.[Lot Quantity] as lot, P.[Free Quantity] as free
FROM [Purchase Price] P
WHERE P.[Item No_] = :id
AND (P.[Ending Date] >= getdate() OR P.[Ending Date] = '1753-01-01 00:00:00.000')
AND (P.[Starting Date] <= getdate() OR P.[Starting Date] = '1753-01-01 00:00:00.000')
ORDER BY P.[Ending Date] ASC
) AS q ON 1=1
) lotandfee,
(
SELECT q.* FROM (SELECT NULL) AS d (dummy) LEFT JOIN (
SELECT TOP 1 P.[Starting Date] as next_promo
FROM [Purchase Price] P
WHERE P.[Item No_] = :id
AND P.[Minimum Quantity] = 1
AND P.[Ending Date] > P.[Starting Date]
AND P.[Starting Date] > getdate()
ORDER BY P.[Starting Date] ASC
) AS q ON 1=1
) nextPromo