powered by simpleCommunicator - 2.0.48     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Разный порядок записей в "почти" одинаковых запросах.
4 сообщений из 4, страница 1 из 1
Разный порядок записей в "почти" одинаковых запросах.
    #40119785
Коваленко Дмитрий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть сбойный тест EF Core.

Раскопки показывают , что два "почти одинаковых" (под)запроса возвращают записи в разном порядке. У обоих интересует только первая запись результата.

Можно было бы забить, но может ещё "кому-нибудь" будет интересно покопаться.

База (FB3.0.8.33506) приатачена.

Скрипт таблицы Orders
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
/******************************************************************************/
/***                Generated by IBExpert 14.12.2021 1:06:34                ***/
/******************************************************************************/
SET SQL DIALECT 3;

CREATE TABLE "Orders" (
    "OrderID"     BIGINT NOT NULL,
    "CustomerID"  VARCHAR(500),
    "EmployeeID"  INTEGER,
    "OrderDate"   TIMESTAMP
);

ALTER TABLE "Orders" ADD CONSTRAINT "PK_Orders" PRIMARY KEY ("OrderID");

ALTER TABLE "Orders" ADD CONSTRAINT "FK_Orders_Customers_Customer~" FOREIGN KEY ("CustomerID") REFERENCES "Customers" ("CustomerID") ON DELETE NO ACTION ON UPDATE NO ACTION;

CREATE INDEX "IX_Orders_CustomerID" ON "Orders" ("CustomerID");


Скрипт таблицы Order Details
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
/******************************************************************************/
/***                Generated by IBExpert 14.12.2021 1:09:53                ***/
/******************************************************************************/
SET SQL DIALECT 3;

CREATE TABLE "Order Details" (
    "OrderID"    BIGINT NOT NULL,
    "ProductID"  INTEGER NOT NULL,
    "UnitPrice"  DECIMAL(18,2) NOT NULL,
    "Quantity"   SMALLINT NOT NULL,
    "Discount"   FLOAT NOT NULL
);

ALTER TABLE "Order Details" ADD CONSTRAINT "PK_Order Details" PRIMARY KEY ("OrderID", "ProductID");

ALTER TABLE "Order Details" ADD CONSTRAINT "FK_Order Details_Orders_Orde~" FOREIGN KEY ("OrderID") REFERENCES "Orders" ("OrderID") ON DELETE CASCADE ON UPDATE NO ACTION;
ALTER TABLE "Order Details" ADD CONSTRAINT "FK_Order Details_Products_Pr~" FOREIGN KEY ("ProductID") REFERENCES "Products" ("ProductID") ON DELETE CASCADE ON UPDATE NO ACTION;

CREATE INDEX "IX_Order Details_ProductID" ON "Order Details" ("ProductID");


Первый подзапрос , который возвращает правильную (ожидаемую) первую запись:
Код: plsql
1.
2.
3.
4.
SELECT "o1"."OrderID", "o2"."OrderID" AS "OrderID0", "o2"."ProductID", ROW_NUMBER() OVER(PARTITION BY "o1"."OrderID" ORDER BY "o1"."OrderID") AS "row"
FROM "Orders" AS "o1"
     CROSS JOIN "Order Details" AS "o2"
WHERE "o1"."OrderID" = 10248


OrderID OrderID0 ProductID row10248 10285 1 110248 10294 1 2
План запроса
PLAN SORT (JOIN (o1 INDEX (PK_Orders), o2 NATURAL))

Второй подзапрос , возвращающий "неправильную" первую запись:
Код: plsql
1.
2.
3.
4.
SELECT "o1"."OrderID", "o1"."CustomerID", "o1"."EmployeeID", "o1"."OrderDate", "o2"."OrderID" AS "OrderID0", "o2"."ProductID", ROW_NUMBER() OVER(PARTITION BY "o1"."OrderID" ORDER BY "o1"."OrderID") AS "row"
FROM "Orders" AS "o1"
    CROSS JOIN "Order Details" AS "o2"
WHERE "o1"."OrderID" = 10248


OrderID CustomerID EmployeeID OrderDate OrderID0 ProductID row10248 VINET 5 04.07.1996 00:00:00.7070 11005 1 110248 VINET 5 04.07.1996 00:00:00.7070 11006 1 2
План запроса
PLAN SORT (JOIN (o1 INDEX (PK_Orders), o2 NATURAL))
Проблема с OrderID0. Ожидается, что здесь будет 10285 (как в первом запросе).

Эксперименты показывают, что во втором запросе порядок меняется, когда в списке возвращаемых колонок появляется "o1"."CustomerID".

То есть, к примеру, запрос:
Код: plsql
1.
2.
3.
4.
SELECT "o1"."OrderID", /*"o1"."CustomerID",*/ "o1"."EmployeeID", "o1"."OrderDate", "o2"."OrderID" AS "OrderID0", "o2"."ProductID", ROW_NUMBER() OVER(PARTITION BY "o1"."OrderID" ORDER BY "o1"."OrderID") AS "row"
FROM "Orders" AS "o1"
  CROSS JOIN "Order Details" AS "o2"
WHERE "o1"."OrderID" = 10248


Возвращает ожидаемый OrderID0==10285

OrderID EmployeeID OrderDate OrderID0 ProductID row10248 5 04.07.1996 00:00:00.7070 10285 1 1
План запроса
PLAN SORT (JOIN (o1 INDEX (PK_Orders), o2 NATURAL))
-----------
Понятное дело, что это тест кривой. Не первый и, думаю, не последний.

Но тем не менее.

Не понятно, почему "o1"."CustomerID" меняет порядок возвращаемых записей?

Сам тест
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
        [ConditionalTheory]
        [MemberData(nameof(IsAsyncData))]
        public virtual Task Include_collection_SelectMany_GroupBy_Select(bool async)
        {
            return AssertQuery(
                async,
                ss => (from o in ss.Set<Order>().Include(o => o.OrderDetails).Where(o => o.OrderID == 10248)
                       from od in ss.Set<OrderDetail>()
                       select o)
                    .GroupBy(e => e.OrderID)
                    .Select(e => e.OrderBy(o => o.OrderID).FirstOrDefault()),
                entryCount: 4);
        }


Он генерирует два мутных запроса, с выше обозначенными подзапросами:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
SELECT "t0"."OrderID", "t0"."CustomerID", "t0"."EmployeeID", "t0"."OrderDate", "t"."OrderID", "t0"."OrderID0", "t0"."ProductID"
FROM
 (SELECT "o"."OrderID"
  FROM "Orders" AS "o"
  CROSS JOIN "Order Details" AS "o0"
  WHERE "o"."OrderID" = 10248
  GROUP BY "o"."OrderID" ) AS "t"
LEFT JOIN
 (SELECT "t1"."OrderID", "t1"."CustomerID", "t1"."EmployeeID", "t1"."OrderDate", "t1"."OrderID0", "t1"."ProductID"
  FROM
   (SELECT "o1"."OrderID", "o1"."CustomerID", "o1"."EmployeeID", "o1"."OrderDate", "o2"."OrderID" AS "OrderID0", "o2"."ProductID", ROW_NUMBER() OVER(PARTITION BY "o1"."OrderID" ORDER BY "o1"."OrderID") AS "row"
    FROM "Orders" AS "o1"
          CROSS JOIN "Order Details" AS "o2"
    WHERE "o1"."OrderID" = 10248) AS "t1"
  WHERE "t1"."row" <= 1 ) AS "t0"
ON "t"."OrderID" = "t0"."OrderID"
ORDER BY "t"."OrderID", "t0"."OrderID", "t0"."OrderID0", "t0"."ProductID"


SELECT "o3"."OrderID", "o3"."ProductID", "o3"."Discount", "o3"."Quantity", "o3"."UnitPrice", "t"."OrderID", "t0"."OrderID", "t0"."OrderID0", "t0"."ProductID"
FROM
 (SELECT "o"."OrderID"
  FROM "Orders" AS "o"
  CROSS JOIN "Order Details" AS "o0"
  WHERE "o"."OrderID" = 10248
  GROUP BY "o"."OrderID" ) AS "t"
 LEFT JOIN
  (SELECT "t1"."OrderID", "t1"."OrderID0", "t1"."ProductID"
   FROM
    (SELECT "o1"."OrderID", "o2"."OrderID" AS "OrderID0", "o2"."ProductID", ROW_NUMBER() OVER(PARTITION BY "o1"."OrderID" ORDER BY "o1"."OrderID") AS "row"
     FROM "Orders" AS "o1"
          CROSS JOIN "Order Details" AS "o2"
     WHERE "o1"."OrderID" = 10248) AS "t1"
   WHERE "t1"."row" <= 1 ) AS "t0"
 ON "t"."OrderID" = "t0"."OrderID"
 INNER JOIN "Order Details" AS "o3" ON "t0"."OrderID" = "o3"."OrderID"
ORDER BY "t"."OrderID", "t0"."OrderID", "t0"."OrderID0", "t0"."ProductID"


Для MSSQL генерируются точно такие же запросы и с ним тест отрабатывает без проблем.

---
Несколько раз просмотрел, вроде все правильно описал :)
...
Рейтинг: 0 / 0
Разный порядок записей в "почти" одинаковых запросах.
    #40119789
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Коваленко Дмитрий
Проблема с OrderID0. Ожидается, что здесь будет 10285 (как в первом запросе).
Ни в первом, ни во втором запросе ты не можешь ожидать никакого упорядочения кроме как по o1.OrderID.

Коваленко Дмитрий
Не понятно, почему "o1"."CustomerID" меняет порядок возвращаемых записей?
Жирное поле - сильно влияет на сортировку всего резалтсета.
Никто никогда не обещал одинаковый порядок для частично отсортированных данных.

Коваленко Дмитрий
Для MSSQL генерируются точно такие же запросы и с ним тест отрабатывает без проблем.
Запросы кривые, а в MSSQL я бы проверил план и наличие кластерного индекса в "Order Details".
...
Рейтинг: 0 / 0
Разный порядок записей в "почти" одинаковых запросах.
    #40119872
jonik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Коваленко Дмитрий,

странно, а почему вы ожидаете такой порядок? Вы его явно не указали!
Сделайте это явно и всё
ROW_NUMBER() OVER(PARTITION BY "o1"."OrderID" ORDER BY "o1"."OrderID", "o2"."OrderID") AS "row"
...
Рейтинг: 0 / 0
Разный порядок записей в "почти" одинаковых запросах.
    #40119880
WildSery
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Коваленко Дмитрий
Первый подзапрос , который возвращает правильную (ожидаемую) первую запись:
В твоём запросе ВСЕ первые записи правильные
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Разный порядок записей в "почти" одинаковых запросах.
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]