Выберите все уникальные значения в таблице SQL с дополнительной информацией

Я пытаюсь найти первые 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, поэтому понятия не имею, как обойти эту проблему. Мне не нужно, чтобы результаты форматировались таким образом.

FIRST() — странная птица. В реальных реляционных базах данных не существует настоящей «первой» строки без явного ORDER BY. Базы данных могут, а иногда и будут давать вам разные результаты для одного и того же sql для одних и тех же данных от запуска к запуску запроса.
Joel Coehoorn 22.07.2024 17:25

1 — SQL Server 2008? Серьезно? Его не поддерживают уже 4 или 5 лет. 2. Не знаете, что именно делает функция first в Access, может быть, посмотрите first_value ?

Andrew 22.07.2024 17:25

Кроме того, SQL Server 2008 уже официально вышел из эксплуатации более 5 лет назад. Это означает, что уже давно нет никаких исправлений... даже критических обновлений безопасности. Продолжать ее использовать опасно и безответственно, тем более, что любая база данных, достаточно маленькая, чтобы поместиться в Access, скорее всего, также поместится в бесплатную версию Express Edition текущей версии. Если вы перейдете к более позднему выпуску, вы можете хотя бы использовать First_Value(), который позволит вам установить ПОРЯДОК ПО.

Joel Coehoorn 22.07.2024 17:27

Это странный запрос. Насколько мне известно, нет документации о том, что MS Access считает строкой FIRST группы. Другими словами, вы получите значения из произвольно выбранных строк. Затем вы пытаетесь удалить дубликаты с помощью DISTINCT, но дубликатов быть не может, потому что вы группируете по коду налоговой группы и выбираете код налоговой группы. Я предлагаю, прежде чем пытаться преобразовать этот запрос из MS Access в SQL Server, подумать, для чего на самом деле предназначен этот запрос, и исправить это.

Thorsten Kettner 22.07.2024 18:50

Торстен, ты прав. Я удалил DISTINCT и получил те же результаты.

WhyteDem0n 22.07.2024 19:04
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
88
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вам необходимо перейти на более новую версию 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 год. К сожалению, версия вышла из-под моего контроля, и мне пока приходится работать с ней. Нет ли обходного пути для достижения желаемых результатов с используемой версией продукта?

WhyteDem0n 22.07.2024 17:53

Ну... покажи им этот пост. В любом случае, альтернатива намного сложнее: написание логики для вычисления первого значения для каждого набора, а затем присоединение к подзапросам, которые соответствуют только этим строкам.

Joel Coehoorn 22.07.2024 18:08

Найден обходной путь, реализация которого займет некоторое время, но по сути мы собираемся создать базу данных Access со связанными таблицами, указывающими на базу данных SQL. Уже протестировал пару запросов и работают без доработок. Судя по всему, у нас есть план по обновлению до SQL 2022, но нам нужно устранить некоторые недостатки в нашей текущей настройке, прежде чем мы сможем перейти на нее.

WhyteDem0n 22.07.2024 19:32

Попробуйте с 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-сервер.

WhyteDem0n 22.07.2024 18:37

О, тогда попробуйте базовую конкатенацию - см. расширенный ответ, пожалуйста. Но, конечно, пришло время обновления.

Gustav 23.07.2024 08:09

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