使用动态数据透视查询时已多次指定列?

时间:2018-09-21 03:57:25

标签: sql-server pivot

因此,假设我有两个表table1table2,我想使用cte视图uvw_TestView进行透视。

table1

id1 | name | locationCode
----|------|-----------------
1   | a    | 3
2   | b    | 1
3   | c    | 2

table2

id2 | id1 | StudyName | dateStudy
----|-----|-----------|------
1   | 1   | Math      | 2015-05-23
2   | 1   | Chemistry | 2015-06-20
3   | 2   | Math      | 2016-09-02
4   | 3   | Physics   | 2016-12-26
5   | 2   | Chemistry | 2017-01-05
6   | 2   | Math      | 2017-06-06
7   | 3   | Chemistry | 2018-02-22

这里的景色只是table1的人们学习的地方。

如果日期从2015-05-01过滤到2017-01-01

,则预期结果将是这样的
id1 | name | Math       | Chemistry  | Physics 
1   | a    | 2015-05-23 | 2015-06-20 |   ---
2   | b    | 2016-09-02 |   ---      |   ---
3   | c    |   ---      |   ---      |   2016-12-26

很抱歉,我无法在此处显示真实的查询,但我尝试使其与之相似。

我尝试使用不带日期过滤器的此查询

DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX), @dtDate1 DATETIME, @dtDate2 DATETIME;
SET @dtDate1 = '2015-05-01'
SET @dtDate2 = '2017-01-01'
SET @columns = N'';
SELECT @columns += N', ' + QUOTENAME(StudyName)
  FROM (SELECT DISTINCT t2.StudyName FROM dbo.table2 AS t2) AS x;

SET @sql = N'
WITH cte AS
(
    SELECT * FROM dbo.uvw_TestView WHERE idView = '001'
    UNION ALL
    SELECT a.* FROM dbo.uvw_TestView a INNER JOIN cte b ON a.ParentID = b.idView
SELECT * FROM
    (SELECT DISTINCT * FROM cte) ct
INNER JOIN (
    SELECT p.*, ' + STUFF(@columns, 1, 2, '') + '
    FROM
    (
        SELECT DISTINCT
            tb1.id1,
            tb1.name,
            tb2.dateStudy,
            tb2.StudyName
        FROM dbo.table1 AS tb1
        INNER JOIN dbo.table2 tb2 tb2
        ON tb1.id1 = tb2.id1
    ) AS j
    PIVOT
    (
      MIN(dateStudy) FOR StudyName IN ('
      + STUFF(REPLACE(@columns, ', [', ',['), 1, 1, '')
      + ')
    ) AS p) tbl ON tbl.id1 = ct.id1';
PRINT @sql;
EXEC sp_executesql @sql;

但是出现错误The column 'Math' was specified multiple times for 'tbl'.

我也尝试过使用日期过滤器

SELECT @columns += N', ' + QUOTENAME(StudyName)
  FROM (SELECT DISTINCT t2.StudyName FROM dbo.table2 AS t2) AS x;

SET @sql = N'
WITH cte AS
(
    SELECT * FROM dbo.uvw_TestView WHERE idView = '001'
    UNION ALL
    SELECT a.* FROM dbo.uvw_TestView a INNER JOIN cte b ON a.ParentID = b.idView
SELECT * FROM
    (SELECT DISTINCT * FROM cte) ct
INNER JOIN (
    SELECT p.*, ' + STUFF(@columns, 1, 2, '') + '
    FROM
    (
        SELECT DISTINCT
            tb1.id1,
            tb1.name,
            tb2.dateStudy,
            tb2.StudyName
        FROM dbo.table1 AS tb1
        INNER JOIN dbo.table2 tb2 tb2
        ON tb1.id1 = tb2.id1
    ) AS j
    PIVOT
    (
      MIN(dateStudy) FOR StudyName IN ('
      + STUFF(REPLACE(@columns, ', [', ',['), 1, 1, '')
      + ')
    ) AS p) tbl ON tbl.id1 = ct.id1 where tbl.dateStudy BETWEEN ''' + @dtDate1 +''' AND ''' + @dtDate2;

并得到错误String or binary data would be truncated.

那么,我如何解决此错误以获得结果?

1 个答案:

答案 0 :(得分:1)

我看到您有一个enum image_format { IMAGE_FORMAT_UBI = 0, IMAGE_FORMAT_BOOT, IMAGE_FORMAT_RAW, IMAGE_FORMAT_N }; // v--- empty static image_format_validator image_format_validators[ ] = { [IMAGE_FORMAT_UBI] = &image_format_validator_ubi, [IMAGE_FORMAT_BOOT] = &image_format_validator_boot, [IMAGE_FORMAT_RAW] = NULL }; #define IFV_N (sizeof image_format_validators/sizeof image_format_validators[0]) _Static_assert(IFV_N == IMAGE_FORMAT_N, "Unexpected size"); 声明。但是您是否看过查询?

错误PRINT @sql;是由于此行

The column 'Math' was specified multiple times for 'tbl'.

您的SELECT p.*, ' + STUFF(@columns, 1, 2, '') + ' 将包含诸如columns之类的列列表,而[Chemistry], [Math]实际上包含来自p.*结果的所有列。所以那些枢轴列是重复的

您可以改为使用PIVOT,它应该足够了。