Я, конечно же, согласен с комментариями относительно нормализации базы данных. В идеале вы должны иметь отдельную таблицу с внешними ключами, связанными с IP-окном и сканером.
Для облегчения нормализации данных вы можете посмотреть функцию UNPIVOT
. Например.
CREATE TABLE T (ID INT NOT NULL, Scanner1 DATETIME, Scanner2 DATETIME, Scanner3 DATETIME, Scanner4 DATETIME)
INSERT INTO T VALUES
(1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
(2, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL),
(3, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, NULL),
(4, CURRENT_TIMESTAMP, NULL, NULL, NULL),
(5, NULL, NULL, NULL, NULL)
SELECT ID, Scanner, ScannedDate
FROM T
UNPIVOT
( ScannedDate
FOR Scanner IN ([Scanner1], [Scanner2], [Scanner3], [Scanner4])
) UnPvt
ORDER BY ID, Scanner
который будет возвращать что-то вроде этого:
ID Scanner ScannedDate
-----------------------------------
1 Scanner1 May 31 2012 10:40AM
1 Scanner2 May 31 2012 10:40AM
1 Scanner3 May 31 2012 10:40AM
1 Scanner4 May 31 2012 10:40AM
2 Scanner1 May 31 2012 10:40AM
2 Scanner2 May 31 2012 10:40AM
2 Scanner3 May 31 2012 10:40AM
3 Scanner1 May 31 2012 10:40AM
3 Scanner2 May 31 2012 10:40AM
4 Scanner1 May 31 2012 10:40AM
Это все еще имеет проблему того, чтобы выписывать столбцы вручную, однако вы можете динамически создать UNPIVOT заявление тоже:
DECLARE @SQL NVARCHAR(MAX) = '',
@Columns NVARCHAR(MAX) = ''
SELECT @Columns = @Columns + ',' + QUOTENAME(Name)
FROM SYS.COLUMNS
WHERE OBJECT_ID = OBJECT_ID(N'T')
AND LEFT(Name, 7) = 'Scanner'
SET @SQL = 'SELECT ID, Scanner, ScannedDate
FROM T
UNPIVOT
( ScannedDate
FOR Scanner IN (' + STUFF(@Columns, 1, 1, '') + ')
) UnPvt
ORDER BY ID, Scanner'
DECLARE @UnPivot TABLE (ID INT, Scanner VARCHAR(50), ScannedDate DATETIME)
INSERT INTO @UnPivot
EXECUTE SP_EXECUTESQL @SQL
SELECT *
FROM @UnPivot
Наконец, если вам нужно преобразовать нормализованные данные обратно в плоское представление, это все равно можно выполнить с помощью функции PIVOT
(это предполагает @SQL и @Columns ar е уже определено выше):
CREATE TABLE ##UnPivot (ID INT, Scanner VARCHAR(50), ScannedDate DATETIME)
INSERT INTO ##UnPivot
EXECUTE SP_EXECUTESQL @SQL
SELECT *
FROM ##UnPivot
SET @SQL = 'SELECT ID' + @Columns + '
FROM ##Unpivot
PIVOT
( MAX(ScannedDate)
FOR Scanner IN (' + STUFF(@Columns, 1, 1, '') + ')
) UnPvt
ORDER BY ID'
EXECUTE SP_EXECUTESQL @SQL
DROP TABLE ##UnPivot
Я поставил полный рабочий пример динамически unpivoting данные, а затем поворачиваясь снова на SQL Fiddle
EDIT
У меня есть просто понял, что я фактически не ответил на исходный вопрос, я просто посоветовал, как нормализовать данные.Вот как вы можете сделать это без ручного ввода из столбцов:
DECLARE @SQL NVARCHAR(MAX) = '',
@Columns NVARCHAR(MAX) = ' WHERE 1 = 1 '
SELECT @Columns = @Columns + 'AND ' + QUOTENAME(Name) + ' IS NOT NULL '
FROM SYS.COLUMNS
WHERE OBJECT_ID = OBJECT_ID(N'T')
AND LEFT(Name, 7) = 'Scanner'
SET @SQL = 'UPDATE T SET Completed = 1' + @Columns
EXECUTE SP_EXECUTESQL @SQL
Опять же, есть рабочий пример на SQL Fiddle
Я хотел бы рассмотреть нормализации базы данных и не имеющие 1 поле для каждого сканера, вы добавив новое поле, когда вы получите новый сканер? –
Я бы ожидал, что у каждого сканера есть какой-то уникальный идентификатор - правильно? Таким образом, вы должны иметь возможность нормализовать это в отдельную таблицу, которая будет содержать идентификатор сканера и столбец «завершен» ... –
может у plz разместить структуру таблицы – Zia