Transact-SQL ранг (сортировка) необработанных голосов

Я застрял при разработке алгоритма сортировки необработанных голосов. Таблица голосов выглядит так:

CREATE TABLE [dbo].[Votes](
  RecordId int IDENTITY(1,1) NOT NULL,
  FirstNameId int NOT NULL,
  SecondNameId int NOT NULL,
  FirstPreferred bit NULL)

FirstNameId и SecondNameId являются ссылками на PK одной и той же таблицы имен. Пользователь голосует парами либо за имя, либо за второе имя, и в зависимости от того, что столбец FirstPreferred принимает значение 1 (True) или 0 (false).

Пожалуйста помоги. Я действительно не придумал ничего лучше, чем навести курсор на таблицу голосов.

Таблица голосов уже заполнена данными, поэтому я не могу влиять на процесс голосования.

Данные голосования:

RecordId  FirstNameId  SecondNameId  FirstPreferred
   1          41            60            0
   2          49           108            0
   3         110           118            0
   4          35            41            0
   5          15           100            0
   6          12            74            1
   7          16           122            1
   8          46           118            0
   9          46           105            1
  10          93           117            0

Пример данных из таблицы имен:

NameId    Name
  5      Nicolas
  6      Sergio
 11      Alexander
 12      Alexei
 13      Albert
 15      Anatoly
 16      Andreas

1 ответ

Решение

Если я вас правильно понимаю, вы хотите посчитать, как часто за каждое имя голосовали, а затем вывести результаты, отсортированные по этому количеству? Если это так, вы можете использовать это:

CREATE TABLE dbo.Names(
  NameId INT,
  FullName NVARCHAR(20)
)
CREATE TABLE [dbo].[Votes](
  RecordId int IDENTITY(1,1) NOT NULL,
  FirstNameId int NOT NULL,
  SecondNameId int NOT NULL,
  FirstPreferred bit NULL)
GO
INSERT INTO dbo.Names
VALUES(1,'p1'),
      (2,'p2'),
      (3,'p3'),
      (4,'p4');


INSERT INTO dbo.Votes
VALUES (1,2,1),
       (1,3,1),
       (1,4,0),
       (2,3,1),
       (2,4,0),
       (3,4,0);

WITH VotedNames AS(       
SELECT CASE WHEN FirstPreferred = 1
            THEN FirstNameId
            ELSE SecondNameId
       END AS NameId
FROM dbo.Votes
)
SELECT NameId, COUNT(1) AS Votes
FROM VotedNames
GROUP BY NameId
ORDER BY Votes DESC;


WITH VotedNames AS(       
SELECT CASE WHEN FirstPreferred = 1
            THEN FirstNameId
            ELSE SecondNameId
       END AS NameId
FROM dbo.Votes
)
,VoteCounts AS(
SELECT NameId, COUNT(1) AS Votes
FROM VotedNames
GROUP BY NameId
)
SELECT n.*,ISNULL(v.Votes,0) AS Votes
FROM dbo.Names AS n
LEFT JOIN VoteCounts AS v
ON n.NameId = v.NameId
ORDER BY v.Votes DESC;

Первый выбор исключает NameIds, за которые вообще не проголосовали. Второй выбор присоединяется к таблице имен и включает также голосов без голосования.

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