Что не так с синтаксисом SQL моего запроса?

У меня есть такой запрос в моей программе:

SELECT customer.Id, customer.FirstName, customer.LastName, SUM(PeriodHours) AS SUMPeriodHours, PeriodDay 
FROM (
      (SELECT CustomerId, 
              (UNIX_TIMESTAMP(taskinterval.EndDateUtc) - UNIX_TIMESTAMP(taskinterval.StartDateUtc)) / 3600 AS PeriodHours, 
              date(taskinterval.StartDateUtc) as PeriodDay
       FROM taskinterval
       WHERE StartDateUtc > @STARTDATE and StartDateUtc<@ENDDATE
      ) AS tmptbl
 ) 
INNER JOIN customer on customer.Id = tmptbl.CustomerId
GROUP BY PeriodDay, customer.Id, customer.FirstName, customer.LastName

Это не работает ни в коде моей программы, ни в SqlWorkbench, когда я заменяю «@ENDDATE» и «@STARTDATE».

Он отлично работает в MariaDB 10.3.32, но в MySQL 8.0.35 не работает, отображается такая ошибка:


Код ошибки: 1064. У вас ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, чтобы найти правильный синтаксис для использования рядом с ') Внутреннее присоединение клиента к клиенту.Id = tmptbl.CustomerId group'


Эта ошибка кажется мне неясной. Я просмотрел эту статью: https://mariadb.com/kb/en/incompatabilities-and-feature-differences-between-mariadb-10-4-and-mysql-8-/, но ничего не нашел это может помочь мне с этим вопросом. Как исправить этот запрос, чтобы сделать его совместимым с MySQL?

Что не так с синтаксисом SQL моего запроса? Лишняя скобка, которая оборачивает подзапрос (закрывающая скобка, которая начинает фрагмент кода в сообщении об ошибке, и соответствующая открывающая скобка). В MySQL это означает «преобразовать выходные данные подзапроса в скалярное значение». Удалить их.

Akina 17.05.2024 09:42

Почему это закрыли? Разве будущим читателям не важно знать, что у MySQL есть проблема с дополнительными круглыми скобками, которые другие СУБД считают только излишними? Я проголосовал за то, чтобы это снова открылось.

Thorsten Kettner 17.05.2024 10:52

Если у MySQL есть какие-либо проблемы с этими круглыми скобками, действительно ли это связано с программированием?

Nico Haase 17.05.2024 11:40

@Нико Хаазе: Да, это так. Различные СУБД имеют разные диалекты SQL. Некоторые позволяют группировать по псевдонимам, другие — нет. Таким образом, если кто-то попытается сгруппировать по псевдониму, и его СУБД выдаст ошибку, он найдет ответ на stackoverflow, что некоторые СУБД поддерживают синтаксис, а их нет. То же самое. Обычно СУБД справляются с дополнительными круглыми скобками, но MySQL здесь особенный. Если программист наткнется на эту ошибку, он будет рад найти объяснение в stackoverflow, потому что я почти уверен, что это трудно найти в документации MySQL, если вообще найти.

Thorsten Kettner 17.05.2024 12:30

Псевдоним tmptbl находится в неправильном положении. Должно быть после производной таблицы. (Т.е. после последней закрывающей правой скобки.) В соответствии со стандартом ISO/ANSI SQL!

jarlh 17.05.2024 17:50
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
5
97
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Кажется, у вас есть лишняя скобка. Попробуй это

    Select
    customer.Id,
    customer.FirstName,
    customer.LastName,
    SUM(PeriodHours) as SUMPeriodHours,
    PeriodDay
    from
    (
    SELECT
      CustomerId,
      (
        UNIX_TIMESTAMP(taskinterval.EndDateUtc) - UNIX_TIMESTAMP(taskinterval.StartDateUtc)
      ) / 3600 as PeriodHours,
      date(taskinterval.StartDateUtc) as PeriodDay
    FROM
      taskinterval
    where
      StartDateUtc > @STARTDATE
      and StartDateUtc < @ENDDATE
    ) as tmptbl
     Inner Join customer on customer.Id = tmptbl.CustomerId
    group by
  PeriodDay,
  customer.Id,
  customer.FirstName,
  customer.LastName
Ответ принят как подходящий

Непосредственной причиной является дополнительная ( .. ):

FROM (( SELECT ... FROM taskinterval))

должен быть

FROM ( SELECT ... FROM taskinterval)

Чтобы избежать таких досадных ошибок, сделайте запрос простым, разбейте его на легко читаемые фрагменты, в вашем случае CTE:

WITH tmptbl AS (
  SELECT CustomerId, 
         (UNIX_TIMESTAMP(taskinterval.EndDateUtc) - UNIX_TIMESTAMP(taskinterval.StartDateUtc)) / 3600 AS PeriodHours, 
         date(taskinterval.StartDateUtc) AS PeriodDay
    FROM taskinterval
   WHERE StartDateUtc > @STARTDATE AND StartDateUtc < @ENDDATE 
)

  SELECT customer.Id, 
         customer.FirstName, 
         customer.LastName, 
         SUM(PeriodHours) AS SUMPeriodHours, 
         PeriodDay 
    FROM tmptbl
    JOIN customer ON customer.Id = tmptbl.CustomerId
GROUP BY customer.Id, 
         customer.FirstName, 
         customer.LastName,
         PeriodDay 

Этот код используется в программе на C#. Сомневаюсь, что вы можете упаковать ДВА запроса в вызов MySqlCommand. Хотя выглядит аккуратно

Ivan P. 17.05.2024 10:58

@Иван П.: обратите внимание, что это один запрос (который можно выполнить как обычно). Близкая аналогия: у нас может быть одна программа с несколькими методами (не один огромный Main)

Dmitry Bychenko 17.05.2024 11:36

@ИванП. Это разрешено, см. dev.mysql.com/doc/connector-net/en/… опция AllowBatch

Charlieface 17.05.2024 14:41

Дополнительный ( ... ) разрешен, если он не использует псевдоним таблицы. Это используется для группировки операций над множествами, таких как UNION и INTERSECT. dbfiddle.uk/a5Esl2So

Charlieface 17.05.2024 14:43

Да, я вижу, что FROM (( SELECT ... )) AS tmptbl ) работает на MySQL 8.9.36.

Rick James 19.05.2024 02:07

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