Я пытаюсь найти первые SeqGrp
и SeqNum
из первых уникальных значений TaxGroupCode
. У меня был этот запрос в базе данных MS Access (показанной ниже), но недавно мы начали использовать вместо него SQL Server 2008.
Однако, похоже, FIRST
не является допустимой функцией в T-SQL (по крайней мере, в этой версии).
SELECT
FIRST(DesotoCoPA_Trims.SeqGrp) & "-" & FIRST(DesotoCoPA_Trims.SeqNum), "Tax District " & DesotoCoPA_Trims.TaxGroupCode AS Sample
FROM
DesotoCoPA_Trims
GROUP BY
DesotoCoPA_Trims.TaxGroupCode;
Это производит:
GrpSeq Sample
-----------------------
2-28 Tax District 2
5-31 Tax District 3
6-2123 Tax District 7
6-2128 Tax District 1
6-9694 Tax District 6
Я относительно новичок в SQL, поэтому понятия не имею, как обойти эту проблему. Мне не нужно, чтобы результаты форматировались таким образом.
1 — SQL Server 2008? Серьезно? Его не поддерживают уже 4 или 5 лет. 2. Не знаете, что именно делает функция first
в Access, может быть, посмотрите first_value
?
Кроме того, SQL Server 2008 уже официально вышел из эксплуатации более 5 лет назад. Это означает, что уже давно нет никаких исправлений... даже критических обновлений безопасности. Продолжать ее использовать опасно и безответственно, тем более, что любая база данных, достаточно маленькая, чтобы поместиться в Access, скорее всего, также поместится в бесплатную версию Express Edition текущей версии. Если вы перейдете к более позднему выпуску, вы можете хотя бы использовать First_Value()
, который позволит вам установить ПОРЯДОК ПО.
Это странный запрос. Насколько мне известно, нет документации о том, что MS Access считает строкой FIRST
группы. Другими словами, вы получите значения из произвольно выбранных строк. Затем вы пытаетесь удалить дубликаты с помощью DISTINCT
, но дубликатов быть не может, потому что вы группируете по коду налоговой группы и выбираете код налоговой группы. Я предлагаю, прежде чем пытаться преобразовать этот запрос из MS Access в SQL Server, подумать, для чего на самом деле предназначен этот запрос, и исправить это.
Торстен, ты прав. Я удалил DISTINCT и получил те же результаты.
Вам необходимо перейти на более новую версию SQL Server. Для этого есть две причины.
Одна из причин заключается в том, что SQL Server 2008 безнадежно устарел. За более чем 5 лет к нему не было никаких исправлений или обновлений... даже критических обновлений безопасности. Продолжать его использовать опасно и безответственно. Я понимаю, что вы, возможно, не в состоянии внести это изменение напрямую, но вы, вероятно, в состоянии продвинуть эту потребность (не желание!) вверх по цепочке.
Другая причина заключается в том, что новые версии SQL Server позволят вам легко решить эту проблему.
Чтобы понять, как это сделать, сначала мне нужно кое-что объяснить в теории реляционных множеств. Реальные реляционные базы данных вообще не имеют никакого понятия о первом или последнем элементе набора. При отсутствии явной директивы ORDER BY
они могут возвращать строки в любом удобном порядке. Обычно это соответствует порядку, хранящемуся на диске или в первичном ключе, но есть ряд вещей, которые могут изменить это для данного выполнения запроса. То есть база данных может (а иногда БУДЕТ) выдавать разные результаты из одного и того же sql для одних и тех же данных.
Это не хорошо. Функция First()
из Access нарушает этот принцип и поэтому никогда не добавлялась в большинство серьезных продуктов баз данных.
В последних версиях SQL Server есть функция, называемая оконными функциями, одна из которых — First_Value(). Эта функция является частью стандарта ANSI и использует предложение OVER
, куда вы включаете определение ORDER BY
, чтобы получить детерминированные результаты. Это ближайшее прямое соответствие функции First()
из доступа.
Также часто проще использовать row_number(), а затем обернуть запрос так, чтобы предложение WHERE
ограничивало результаты строками, где row_number()
было 1
(это также заменяет предложение GROUP BY
).
Но эти функции пока недоступны в SQL Server 2008.
Поскольку нам все равно нужно обновиться, вместо того, чтобы говорить о том, в какой версии добавлена функция оконной функции, я расскажу о поддержке и исправлениях. С этой точки зрения минимальная версия SQL Server, которую вы должны использовать сегодня (июль 2024 г.), — это SQL Server 2016 (формальный конец жизни — июль 2026 г.), но пока вы работаете над ней, вы также можете перейти на более новую версию. Например, SQL Server 2022 должен продолжать получать обновления безопасности до 2033 года.
Хорошей новостью является то, что любая база данных, достаточно маленькая, чтобы поместиться в MS Access, также, вероятно, легко впишется в пределы бесплатной версии Express Edition текущей версии SQL Server. Стоимость вряд ли станет препятствием даже для коммерческого использования, если размер файла Access не превышает 10 ГБ. И если вы не можете установить это из-за того, что операционная система слишком старая, это тоже критическая проблема.
Поверьте мне, я поднял те же проблемы, как только был упомянут 2008 год. К сожалению, версия вышла из-под моего контроля, и мне пока приходится работать с ней. Нет ли обходного пути для достижения желаемых результатов с используемой версией продукта?
Ну... покажи им этот пост. В любом случае, альтернатива намного сложнее: написание логики для вычисления первого значения для каждого набора, а затем присоединение к подзапросам, которые соответствуют только этим строкам.
Найден обходной путь, реализация которого займет некоторое время, но по сути мы собираемся создать базу данных Access со связанными таблицами, указывающими на базу данных SQL. Уже протестировал пару запросов и работают без доработок. Судя по всему, у нас есть план по обновлению до SQL 2022, но нам нужно устранить некоторые недостатки в нашей текущей настройке, прежде чем мы сможем перейти на нее.
Попробуйте с Min и Concat:
SELECT
CONCAT(MIN(DesotoCoPA_Trims.SeqGrp), '-', MIN(DesotoCoPA_Trims.SeqNum)) AS Sequence,
'Tax District ' + DesotoCoPA_Trims.TaxGroupCode AS Sample
FROM
DesotoCoPA_Trims
GROUP BY
DesotoCoPA_Trims.TaxGroupCode;
Альтернативно, если значения не числовые:
SELECT
MIN(DesotoCoPA_Trims.SeqGrp) + '-' + MIN(DesotoCoPA_Trims.SeqNum) AS Sequence,
'Tax District ' + DesotoCoPA_Trims.TaxGroupCode AS Sample
CONCAT также недоступен в 2008 году. Я думаю, здесь необходим серьезный разговор с человеком, отвечающим за наш SQL-сервер.
О, тогда попробуйте базовую конкатенацию - см. расширенный ответ, пожалуйста. Но, конечно, пришло время обновления.
FIRST()
— странная птица. В реальных реляционных базах данных не существует настоящей «первой» строки без явного ORDER BY. Базы данных могут, а иногда и будут давать вам разные результаты для одного и того же sql для одних и тех же данных от запуска к запуску запроса.