У меня есть таблица поиска с множеством столбцов со значениями. Как я могу получить этот вывод из ввода с помощью Microsoft SQL Server?
(Обычно выбирайте имя столбца, где Date = MAX () И ColX to ColZ value = <5.4).

  1. Найти строку с самой последней датой. MAX ( Дата)
  2. Посмотрите в ColX, мое значение 5.4 выше, чем значение ColX? Y / N
  3. Да. Посмотрите в ColY, мое значение 5,4 выше, чем значение ColY? Y / N
  4. Да. Посмотрите в ColZ, мое значение 5,4 выше, чем значение ColZ? Y / N
  5. № Выходной столбец ColY AS Столбец

Ввод

ID        Date                 ColX    ColY    ColZ
-----------------------------------------------------
79185673  2018-11-28 00:00:00     3       5       7
79185673  2018-12-02 00:00:00     2       4       6
79185673  2018-12-04 00:00:00     4       5       6

Вывод

ID        Date                 Column 
--------------------------------------
79185673  2018-12-04 00:00:00    ColY
1
MSvelander 6 Дек 2018 в 00:21

3 ответа

Имена столбцов в DDL фиксируются как метаданные , а не как значения, хранящиеся в строках. Вы можете просмотреть имена столбцов, выбрав из таблицы information_schema.columns. Однако реализовать логику, которую вы запрашиваете, можно с помощью оператора CASE в SQL.

Предполагая, что имя таблицы table1, попробуйте следующий запрос:

declare @compare_value decimal(2,1);
@compare_value = 5.4;

select
t.ID,
t.Date,
case when t.colX <= @compare_value then
    case when t.ColY <= @compare_value then
        case when t.ColZ <= @compare_value then
            'ColZ'
        else
            'ColY'
        end
    else
        'ColY'
    end
else
    'ColX'
end as "Column"
from table1 t
where t.date = (
                   select max(t1.date)
                   from table1 t1
                   where t1.ID = t.ID
               );

Предостережение: код уже вложен в 3 уровня и должен быть вложен для каждого столбца (возможно, до 150 уровней)! Это серьезный код спагетти. Это будет работать, но будет выглядеть грязно. Если объем данных огромен, то производительность также может быть проблемой, поскольку SQL не очень полезен для сложной логики. Было бы лучше использовать SQL для того, чтобы просто выбрать нужные данные и использовать хранимую процедуру или предоставить их через соединение ODBC, например .NET или Python. Тогда сделайте свою сложную логическую обработку там.

1
bruceskyaus 5 Дек 2018 в 22:42

Мы сделаем это поэтапно. Вот настройки данных:

DECLARE @table TABLE
  (
    ID   INTEGER  NOT NULL
   ,Date DATETIME NOT NULL
   ,ColX INTEGER  NOT NULL
   ,ColY INTEGER  NOT NULL
   ,ColZ INTEGER  NOT NULL
  );
INSERT INTO @table
  (ID,Date,ColX,ColY,ColZ)
VALUES
  (79185673, '2018-11-28T00:00:00', 3, 5, 7);
INSERT INTO @table
  (ID,Date,ColX,ColY,ColZ)
VALUES
  (79185673, '2018-12-02T00:00:00', 2, 4, 6);
INSERT INTO @table
  (ID,Date,ColX,ColY,ColZ)
VALUES
  (79185673, '2018-12-04T00:00:00', 4, 5, 6);

Сначала мы найдем запись с максимальной датой.

SELECT TOP (1)
  *
FROM
  @table
ORDER BY
  [Date] DESC

+----------+-------------------------+------+------+------+
|    ID    |          Date           | ColX | ColY | ColZ |
+----------+-------------------------+------+------+------+
| 79185673 | 2018-12-04 00:00:00.000 |    4 |    5 |    6 |
+----------+-------------------------+------+------+------+

Так что это формирует наш базовый набор данных. Оттуда мы хотим UNPIVOT получить все значения столбцов в один столбец. Вам нужно будет ввести все другие имена столбцов в UNPIVOT, но вы, вероятно, можете заставить SSMS выполнить некоторые из этих сценариев за вас, просто используя запрос SELECT TOP N ROWS по умолчанию, а также копирование и вставку. имена столбцов оттуда.

SELECT
  *
FROM
  (
    SELECT
      TOP (1)
      *
    FROM
      @table
    ORDER BY
      [Date] DESC
  ) AS d
  UNPIVOT
  (
    Nums
    FOR ColName IN (ColX, ColY, ColZ)
  ) AS p

+----------+-------------------------+------+---------+
|    ID    |          Date           | Nums | ColName |
+----------+-------------------------+------+---------+
| 79185673 | 2018-12-04 00:00:00.000 |    4 | ColX    |
| 79185673 | 2018-12-04 00:00:00.000 |    5 | ColY    |
| 79185673 | 2018-12-04 00:00:00.000 |    6 | ColZ    |
+----------+-------------------------+------+---------+

Согласно комментариям, числа постоянно увеличиваются по столбцам, поэтому мы можем безопасно сортировать их и поддерживать первоначальный порядок. Но мы заботимся только о числах, которые меньше целевого числа, 5.4 в этом примере. Так что это наше WHERE предложение. И мы хотим, чтобы наибольшее число было меньше 5,4, поэтому мы будем использовать нисходящее предложение ORDER BY. Нам нужно только это единственное значение, поэтому нам нужны только TOP (1) в наших окончательных результатах.

DECLARE @target DECIMAL(5,1) = 5.4;

SELECT TOP (1)
  *
FROM
  (
    SELECT
      TOP (1)
      *
    FROM
      @table
    ORDER BY
      [Date] DESC
  ) AS d
  UNPIVOT
  (
    Nums
    FOR ColName IN (ColX, ColY, ColZ)
  ) AS p
WHERE
  p.Nums < @target
ORDER BY
  p.Nums DESC;

+----------+-------------------------+------+---------+
|    ID    |          Date           | Nums | ColName |
+----------+-------------------------+------+---------+
| 79185673 | 2018-12-04 00:00:00.000 |    5 | ColY    |
+----------+-------------------------+------+---------+
1
Eric Brandt 5 Дек 2018 в 23:33

Я сомневаюсь, что это то, что следует за ОП, основываясь на их комментариях, но исходя из их вопроса, этот ответ будет следующим:

DECLARE @MyValue decimal(2,1) = 5.4

WITH CTE AS(
    SELECT ID,
           [Date],
           ColX,Coly,ColZ,
           ROW_NUMBER() OVER (ORDER BY [Date] DESC) AS RN --PARTITION BY ID?
    FROM TheirTable)
SELECT ID,
       [Date],
       CASE WHEN ColZ < @MyValue THEN 'ColZ'
            WHEN ColY < @MyValue THEN 'ColY'
            WHEN ColX < @MyValue THEN 'ColX'
       END AS [Column]
FROM CTE
WHERE RN = 1;

Их комментарий (под вопросом) является несколько лидирующим, но после обновления его вопроса у них все еще есть только 5 столбцов, поэтому я собираюсь предположить , что 5 - это то, что у них действительно есть. Без реального точного объяснения, это мое «лучшее предположение».

0
Larnu 5 Дек 2018 в 21:53