- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
$sql = "SELECT (SELECT Name FROM dbo.RoutesTypes WHERE RowID = Type) AS Name --Название маршрута
,(SELECT Name FROM dbo.Destinations WHERE Name = '$Src') AS DestA --Пункт отправления
,(SELECT Name FROM dbo.Destinations WHERE Name = '$Dst') AS DestB --Пункт назначения
--,(SELECT COUNT([RowID]) FROM [RoutePartInstances] WHERE [RoutePartType] = RoutesTypes.RowID AND [Occuped] = 0) AS FreePlaces --Количество свободных мест на выбранную часть маршрута
,(SELECT SUM(Cost) From RoutesParts WHERE Ordern >= RoutesTypes.OrderA AND Ordern <= RoutesTypes.OrderB AND InstanceID = Type) AS TicketCost --Стоимость билета на выбранную часть маршрута
,(SELECT SUM(TimeInWay) From RoutesParts WHERE Ordern >= RoutesTypes.OrderA AND Ordern <= RoutesTypes.OrderB AND InstanceID = Type) AS TimeInWay --Время в пути на выбранной части маршрута
--Расчёт времени отправления
,(SELECT DATEADD(Minute,
(SELECT
CASE
WHEN RoutesTypes.OrderA > 1 THEN (SELECT SUM(TimeInWay) From RoutesParts WHERE Ordern < RoutesTypes.OrderA AND InstanceID = Type)+10*(SELECT COUNT(RowID) From RoutesParts WHERE Ordern < RoutesTypes.OrderA AND InstanceID = Type)
ELSE 0
END),[DateStart])) AS DepartureTime
--Расчёт времени прибытия
,(SELECT DATEADD(Minute,
(SELECT SUM(TimeInWay) From RoutesParts WHERE Ordern >= RoutesTypes.OrderA AND Ordern <= RoutesTypes.OrderB AND InstanceID = Type)+10*(SELECT COUNT(RowID) From RoutesParts WHERE Ordern > RoutesTypes.OrderA AND Ordern <= RoutesTypes.OrderB AND InstanceID = Type),
(SELECT DATEADD(Minute,
(SELECT
CASE
WHEN RoutesTypes.OrderA > 1 THEN (SELECT SUM(TimeInWay) From RoutesParts WHERE Ordern < RoutesTypes.OrderA AND InstanceID = Type)+10*(SELECT COUNT(RowID) From RoutesParts WHERE Ordern < RoutesTypes.OrderA AND InstanceID = Type)
ELSE 0
END),[DateStart])))) AS ArrivalTime
--,RoutesTypes.OrderA --Порядок выбранной точки отправления в маршруте. Это нам понадобится при покупке билета
--,RoutesTypes.OrderB --Порядок выбранной точки назначания в маршруте. Это нам понадобится при покупке билета
--,RoutesTable.[RowID] AS RouteID --Идентификатор рейса из таблицы расписаний. Это нам понадобится при покупке билета
--,RoutesTable.[Type] AS RouteTypeID --Идентификатор типа маршрута из таблицы типов маршрутов. Это нам понадобится при покупке билета
FROM [RoutesTable] AS RoutesTable
INNER JOIN (SELECT RoutesParts_A.[InstanceID],RoutesParts_A.[TimeA],RoutesParts_B.TimeB,RoutesParts_A.RowID,RoutesParts_ A.Ordern AS OrderA,RoutesParts_B.Ordern AS OrderB
FROM [RoutesParts] AS RoutesParts_A
INNER JOIN (SELECT [InstanceID],[TimeB],[Ordern] FROM [RoutesParts] WHERE [DestBID] = (SELECT RowID FROM Destinations WHERE Name = '$Dst')) AS RoutesParts_B ON RoutesParts_B.InstanceID = RoutesParts_A.InstanceID
WHERE [DestAID] = (SELECT RowID FROM Destinations WHERE Name = '$Src'))AS RoutesTypes ON RoutesTable.Type = RoutesTypes.InstanceID";
Встретил на форуме phpforum.ru. Человек интересовался почему не работает запрос :)
guest 27.04.2012 13:53 # +14
Steve_Brown 27.04.2012 15:37 # 0
eth0 27.04.2012 15:12 # 0
P.S. Подселекты - злое зло.
3.14159265 27.04.2012 16:16 # 0
А как быть с Not exists?
http://govnokod.ru/9654#comment136160
DBdev 27.04.2012 22:39 # 0
eth0 28.04.2012 13:29 # +1
Не проверял, возможно, сильно specific для базы. На какой-то из DB2/AS400 подзапросы отрабатывали сильно медленнее. Кроме того, как я уже, кажется, писал, можно применять подзапрос в секции where (иногда без него не обойтись в случае update/delete statement). В секции SELECT за подзапрос нужно насиловать кочергой, в секции FROM тоже не должно допускать подобного, кроме случаев, когда база не поддерживает более вкусные ништяки типа WITH, или если другого способа собрать таблицу не существует (например, выборка из VIEW, к которому потребно условие, а портить сам вью не хочется).
В данном коде мы и наблюдаем бесполезные и несвязанные выборки в секции SELECT (особого безумия доставляет SELECT param FROM table WHERE param = var), как и в секции FROM, где можно развернуть без запроса внутри.
Резюмируя:
delete from mytable where id in (select id from othertable group by id having count(*)>1) - годный и валидный запрос, остальное всё от лукавого.
P.S. Да, не стоит забывать, как правильно в том треде отметили, иногда подзапрос может выполняться для каждой строки родительского запроса, чего допускать совсем-совсем нельзя.
Надеюсь, на этом моё изложение видения вопроса всех удовлетворит.
3.14159265 28.04.2012 13:39 # +1
+=1
> в секции FROM тоже не должно допускать подобного, кроме случаев, когда база не поддерживает более вкусные ништяки
+=1
>Не проверял, возможно, сильно specific для базы. На какой-то из DB2/AS400 подзапросы отрабатывали сильно медленнее.
На самом деле больше зависит от типа данных.
Но если рассматривать сферический случай в абсолютном вакууме когда все хорошо написанно при прочих равных подзапрос NOT exists должен быть быстрее.
И вот почему. Not exists - ищет до первого совпадения и потом просто отсеивает запись из выборки.
Left outer join, наоборот выбирает все совпадения и включая те что отсутствуют во второй таблице, и только потом убирает те записи которые нам не нужны. А поскольку в типичных таблицах inner связок зачастую гораздо больше, чем not existов, то работает оно дольше.
То есть Left outer join теоретически делает больше работы джойня всё и потом отсеивая ненужное.
3.14159265 28.04.2012 13:59 # 0
http://explainextended.com/2009/09/15/not-in-vs-not-exists-vs-left-join-is-null-sql-server/
3.14159265 12.09.2012 17:30 # 0
3xdimon 27.04.2012 15:57 # 0
не, не слышал
DBdev 27.04.2012 22:38 # 0
А SQL-скил говную.
Lure Of Chaos 28.04.2012 00:07 # 0
неистребимо стремление джуников "стартовать на второй передаче" - пихать в одно предложение (запрос) всю функциональность.
guest 05.05.2012 01:36 # 0
guest 05.05.2012 02:01 # 0
eth0 05.05.2012 20:46 # +2