2016-10-04 3 views
2

Я пытаюсь заказать набор результатов, он кажется очень простым, но у меня небольшая проблема.Непонятно, как заказать это в SQL Server

У человека может быть несколько типов адресов, NULL, Civic или Mailing. Я хочу, чтобы кто-то, у кого есть NULL-адрес, был указан сверху, но затем их гражданский и почтовый адрес.

Если у вас нет адреса null, тогда их гражданский и/или почтовый адрес приходит после любого, у кого есть null.

Я пробовал заказать по его адресу, просто перечисляет все null сперва, заказывая по названию, адресу, будет работать частично, но не гарантирует, что люди будут null s будут первыми.

Возьмите этот набор, например

ID Person  Address 
------------------------- 
1 Person A Civic 
1 Person A Mailing 
2 Person B NULL 
2 Person B Civic 
2 Person B Mailing 
3 Person C NULL 
3 Person C Civic 
3 Person C Mailing 

Должно быть:

ID Person  Address 
------------------------- 
2 Person B NULL 
2 Person B Civic 
2 Person B Mailing 
3 Person C NULL 
3 Person C Civic 
3 Person C Mailing 
1 Person A Civic 
1 Person A Mailing 
+0

может быть, отсортированный по имени – LKHO

+0

имени или ID. Не имеет значения @TheGameiswar – Jonnny

+0

@TheGameiswar это указано в вопросе 'заказ по имени, адресу, будет работать частично. Сделает это яснее в следующий раз – Jonnny

ответ

1

Тим Biegeleisen имеет право идею в отношении подсчета количества записей, где address IS NULL. Я думаю, что запрос может быть чуть-чуть более элегантно (и, возможно, выполнить немного лучше) с помощью sum с пунктом окна вместо присоединения на ней подзапроса:

SELECT id, person, address 
FROM (SELECT id, 
       person, 
       address, 
       SUM(CASE WHEN PERSON IS NULL THEN 1 ELSE 0 END) OVER 
        (PARTITION BY person) AS s 
     FROM addresses) t 
ORDER BY s DESC, person ASC, address ASC 
+0

Это, похоже, сработает, но быстрее - спасибо – Jonnny

2

Это решение используется подзапрос, который определяет, будет ли или нет каждый ID (человек) имеет значение NULL один его адреса. Если у человека есть значение NULL, то сохраненная сумма будет иметь сумму больше нуля. Эти лица с не менее одного NULL адрес затем заказываются первыми перед лицами без по крайней мере одного NULL. После этого результирующий набор упорядочивается на ID, а затем Address, как вы, возможно, уже делали.

SELECT t1.* 
FROM yourtable 
INNER JOIN 
(
    SELECT ID, 
      SUM(CASE WHEN Address IS NULL THEN 1 END) AS hasNull 
    FROM yourTable 
    GROUP BY ID 
) t2 
    ON t1.ID = t2.ID 
ORDER BY CASE WHEN t2.hasNull > 0 THEN 0 ELSE 1 END, 
     t1.ID, 
     t1.Address 
+0

Спасибо, Тим, есть ли способ увеличить производительность? – Jonnny

+0

Вы делаете это в производстве с таким количеством записей? Или вы планируете запускать этот запрос в автономном режиме для информационных целей? –

+0

это производственный сервер. Это большой набор данных с точки зрения полей, которые являются объединением. Запрос возвращает только 5 тыс. Записей и занимает около 4,5 секунд. Сорт удваивает время. Отличный ответ: :) – Jonnny

1

Попробуйте с этой версией КТР.

;WITH CTE_1 
    AS (SELECT Id, Person, Address, 
       SUM(CASE WHEN PERSON IS NULL THEN 1 ELSE 0 END) OVER 
       (PARTITION BY person) AS RNO 
     FROM addresses) 
    SELECT Id, Person, Address 
    FROM CTE_1 
    ORDER BY RNO DESC, person ASC, address ASC 
0

Просто

select * 
from mytable 
order by min(case when Address is null then 0 else 1 end) over (partition by ID), id, Address; 

Хотя Sql Server не принимает функцию окна в WHERE это нормально в ORDER BY. Поэтому здесь вам не нужен какой-либо подзапрос.

+0

Странно, что ваш пост попал в низкокачественную очередь (глядя на вашего представителя) и даже незнакомец (глядя на моего представителя), что я попрошу вас добавить детали, потому что код -наличные ответы здесь не принимаются. (но это [принятый способ] (http://meta.stackoverflow.com/questions/260411/reviewing-low-quality-posts-answers-without-explanation) для обработки таких случаев). –

+0

Спасибо, что привлек мое внимание к тому, что @ Al.G. Надеюсь, что объяснение, которое я добавил, действительно помогает читателям. – Serg

+0

Да, это «не более отзывчиво». И btw, «просто» - это слово, которое каждый раз удалялось из моих собственных ответов. –

0

Вы можете попробовать это слишком

SELECT * 
FROM @tab 
ORDER BY Person, 
     (CASE 
       WHEN Address IS NULL 
       THEN 'a' 
       ELSE Address 
      END); 
+0

'Вы тоже можете это сделать '- это должно быть' Вы можете использовать это '_ordering_' too'? –