SQL — выбор записей с нечетным номером заданного атрибута

#sql #sql-server #modulus

#sql #sql-сервер #модуль

Вопрос:

Я просто освежаю некоторые SQL — другими словами, я действительно устал — и на данный момент немного застрял. Вероятно, это что-то тривиальное, но посмотрим.

Я хотел бы выбрать всех пользователей, которые обладают нечетным номером определенного атрибута, который не является целым числом (в этом примере TransactionType). Так, например, возьмите следующий тест / не реальную информацию, где эти люди покупают автомобиль или какую-то аналогичную крупную покупку.

 Name TransactionType Date

John   Buy           5/1
John   Cancel        5/1
John   Buy           5/2
Joseph Buy           5/25
Joseph Cancel        5/25
Tanya  Buy           5/28
  

Я бы хотел, чтобы он возвращал людей, у которых было нечетное количество транзакций; другими словами, они в конечном итоге приобрели товар. Итак, в этом случае Джон и Таня будут выбраны, а Джозеф — нет.

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

 count(TransactionType) % 2 != 0
  

в предложении where, но это, очевидно, недопустимо. Любые указатели в правильном направлении были бы очень полезны. Дайте мне знать, если это неясно, и спасибо!

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

1. это все столбцы, которые у вас есть? включено ли время в ваш столбец даты?

2. Нет, это не мои фактические данные. Но, чтобы быть точным с тем, что у меня есть, у меня есть sales_date, который по какой-то причине хранится как varchar -_-

3. включает ли это время?

4. Нет, это не так — это выглядит так: 12-MAY-14, например.

5. есть ли у него увеличивающийся идентификатор или что-то в этом роде, чтобы вы имели представление о том, какой элемент был добавлен первым? вам понадобится что-то вроде этого, чтобы принять мой подход.

Ответ №1:

Вы близки. Вам нужно предложение having вместо предложения where .

 select Name
from table
group by Name
having count(TransactionType) % 2 != 0
  

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

1. Спасибо за вашу помощь. Знал, что мне не хватает чего-то относительно очевидного 🙂

Ответ №2:

Не лучше ли вам получить последний статус по дате транзакции и использовать его, а не полагаться на подсчет TransactionType для определения последнего статуса:

Что-то вроде этого:

 SELECT b.Name, b.TransactionType, b.[Date]
FROM (
   SELECT Name, MAX(t1.[DATE]) latestDate
   FROM [Transactions] t1
   GROUP BY t1.Name
   ) a
INNER JOIN [Transactions] b ON b.Name = a.Name AND a.latestDate = b.[Date]
WHERE b.TransactionType = 'Buy'
  

Предполагая, что ваши даты являются действительными датами с включенным временем, это должно сработать.

Пример скрипки SQL

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