Строка сортировки в базе данных Access

#database #ms-access

#База данных #ms-access

Вопрос:

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

 SELECT DISTINCT tblSample.Version
FROM tblSample
ORDER BY tblSample.Version DESC;
  

Вот пример данных:

 tblSample.Version
1.1.1000
1.2.1654
1.15.1223
1.2.1654
1.1.1000
  

Что я получаю после выполнения запроса:

 1.2.1654
1.15.1223
1.1.1000
  

Что я хочу получить, так это (потому что 15, очевидно,> 2 и 1):

 1.15.1223
1.2.1654
1.1.1000
  

Соответственно, следует учитывать и другие октеты.

Комментарии:

1. Ваши данные неправильно структурированы, если вам нужно сортировать по вложенным строкам.

Ответ №1:

В принципе, если вы хотите sort выполнить x и distinct выполнить a для y, вам нужно сначала выполнить distinct (отсюда и подзапрос)

Используя следующую функцию (измененную из ответа Фредга в этой теме) Примечание: функция использует функцию разделения, которая, я думаю, здесь уместна.

 Public Function ParseText(TextIn As String, X) As Variant
    On Error Resume Next
    Dim var As Variant

    var = Split(TextIn, ".", -1)
    ParseText = var(X)

End Function
  

Вы можете написать этот оператор SQL

 SELECT  t.Version
FROM 
    ( SELECT Distinct tblSample.Version
      FROM tblSample.Version) t
ORDER BY 
    Cint(ParseText([t.Version],0)) DESC , 
    Cint(ParseText([t.Version],1)) DESC , 
    Cint(ParseText([t.Version],2)) DESC;
  

Обновить
Как отметил ХансУп. Вам также необходимо привести к int, чтобы получить правильную сортировку. Вы можете либо сделать это в SQL (как в моем обновленном ответе), либо вы можете сделать это в parseText и вернуть int

Комментарии:

1. Если я что-то не пропустил, этот ответ все равно не будет сортировать 1.15.1223 до 1.2.1654 в порядке убывания.

2. 1 Но вы бы на самом деле использовали этот подход, CF? Мне кажется, что 3 компонента версии по праву принадлежат отдельным числовым полям. Этот атрибут Version похож на один из тех идентификаторов, которые люди создают путем объединения year, Project_ID и так далее. Если вы хотите это, не сохраняйте это; сохраните вложенные элементы и выполните конкатенацию по требованию по мере необходимости.

3. @HansUp. Я согласен, что, вероятно, должно быть три отдельных поля, но, к сожалению, стоимость выполнения этого может не оправдывать ценность этого изменения.

4. До тех пор, пока данные хранятся неправильно, вы рискуете столкнуться с проблемами производительности, поскольку приведенное выше предложение ORDER BY невозможно изменить.

Ответ №2:

То, что вы пытаетесь сделать, аналогично сортировке IP-адресов. Вы можете следовать точно таким же методам, описанным в этой статье, чтобы выполнить то, что вам нужно.

Комментарии:

1. Они не запрашивают отдельные значения… Я думаю, это ключевой момент.

2. Тогда вы должны быть в состоянии интегрировать предложение Конрада Фрикса поместить Distinct в подзапрос. Чтобы упростить работу, вы могли бы сохранить этот подзапрос как отдельный запрос. Обработайте сохраненный запрос как свою базовую таблицу, и все, что я предоставил по ссылке, должно работать оттуда.

Ответ №3:

Сохраните версию в виде 3 числовых полей.

 major minor release
    1     1    1000
    1     2    1654
    1    15    1223
    1     2    1654
    1     1    1000
  

Затем вы можете сгенерировать версию, отсортированную по вашему желанию, с помощью запроса, когда вам это нужно.

 SELECT [major] amp; "." amp; [minor] amp; "." amp; [release] AS Version_num
FROM [SELECT DISTINCT major, minor, release
FROM tblSample]. AS s
ORDER BY s.major DESC , s.minor DESC , s.release DESC;
  

Комментарии:

1. Ваше решение тоже хорошее, но на данный момент я не могу изменить структуру базы данных. Спасибо!

Ответ №4:

Одним из решений было бы: проанализируйте полученные строки, чтобы извлечь числовые значения, при необходимости поместите перед ними начальные 0 и выведите строку. Например, 1.2.1654 становится 0001.0002.1654 (если вы уверены, что нумерация не будет превышать 4 символов). Код:

 Function NormalizeVersion(Inputstring As String) As String
' Creates sortable strings out of version numbers such as 1.6.222
Dim Elements() As String
Dim Counter As Integer
Dim Result As String
Elements = Split(Inputstring, ".")
For Counter = 0 To UBound(Elements)
    Select Case Counter
    Case 0 'First element
        Result = Format(Elements(Counter), "00000")
    Case Else 'Followups
        Result = Result amp; "." amp; Right("0000" amp; Elements(Counter), 5)
    End Select
Next Counter
NormalizeVersion = Result
End Function
  

(включено улучшение производительности HansUp)
Затем вы можете выполнить сортировку по этому.

Напишите функцию VBA, которая делает это за вас, называемую, например, NormalizeVersion, затем вызовите ее в своем запросе, например (air code):

 SELECT DISTINCT NormalizeVersion(tblSample.Version)
FROM tblSample
ORDER BY NormalizeVersion(tblSample.Version) DESC;
  

(код исправлен после комментария)

Комментарии:

1. Я получил сообщение об ошибке ORDER BY clause (NormalizeVersion(tblSample.Version)) conflicts with DISTINCT

2. Вот почему я сказал, что это воздушный код. Так что, вероятно, это что-то вроде: SELECT DISTINCT Normalizeversion(tblSample.Version) FROM tblSample ORDER BY NormalizeVersion(tblSample.Version) DESC;

3. ? Это работает здесь, в примере базы данных, который я только что запустил в Access XP. Смотрите dl.dropbox.com/u/20995033/test.mdb (хотя и с фиктивной функцией VB)

4. Хорошо, но как это решает проблему? Мне все еще нужно избавиться от этих заполняющих нулей. Если я передам этот запрос в качестве источника в list box (который является одним из мест, где я представляю эти данные), то это будет не так просто. Я бы действительно предпочел иметь какой-то предикат, который будет сравнивать две версии. Есть ли какой-нибудь способ?

5. Format(Elements(Counter), "00000") выполняется быстрее, чем Right("0000" amp; Elements(Counter), 5)