سؤال

لدي مجموعة من البيانات التي يتم تنظيمها على النحو التالي:

Timestamp|A0001|A0002|A0003|A0004|B0001|B0002|B0003|B0004 ...
---------+-----+-----+-----+-----+-----+-----+-----+-----
2008-1-1 |  1  |  2  | 10  |   6 |  20 |  35 | 300 |  8
2008-1-2 |  5  |  2  |  9  |   3 |  50 |  38 | 290 |  2    
2008-1-4 |  7  |  7  | 11  |   0 |  30 |  87 | 350 |  0
2008-1-5 |  1  |  9  |  1  |   0 |  25 | 100 |  10 |  0
...

حيث A0001 هي قيمة البند رقم 1 و B0001 هو القيمة ب من البند رقم 1.يمكن أن يكون هناك أكثر من 60 مختلف البنود في جدول كل عنصر له قيمة العمود أ ب قيمة العمود ، وهذا يعني ما مجموعه أكثر من 120 الأعمدة في الجدول.

حيث كنت ترغب في الحصول على 3 عمود النتيجة (البند مؤشر القيمة القيمة ب) أن مبالغ A و B القيم لكل عنصر:

Index | A Value | B Value
------+---------+--------
 0001 |   14    |   125
 0002 |   20    |   260
 0003 |   31    |   950
 0004 |    9    |    10
 .... 

وأنا ذاهب من أعمدة إلى صفوف أتوقع المحورية في الحل ، ولكن أنا لست متأكدا من كيفية اللحم بها.جزء من المشكلة هو كيفية قطاع من A و B على شكل قيم مؤشر العمود.الجزء الآخر هو أنني لم استخدم المحور من قبل ، لذلك أنا عثرة على الجملة الأساسية كذلك.

أعتقد أنه في نهاية المطاف أنا بحاجة إلى أن يكون متعدد خطوة الحل أن الأول يبني اجمال مثل:

ColName | Value
--------+------
A0001   |  14
A0002   |  20
A0003   |  31
A0004   |   9
B0001   | 125
B0002   | 260
B0003   | 950
B0004   |  10

ثم تعديل ColName بيانات قطاع من مؤشر:

ColName | Value | Index | Aspect
--------+-------+-------+-------
A0001   |  14   | 0001  |  A
A0002   |  20   | 0002  |  A
A0003   |  31   | 0003  |  A
A0004   |   9   | 0004  |  A
B0001   | 125   | 0001  |  B
B0002   | 260   | 0002  |  B
B0003   | 950   | 0003  |  B
B0004   |  10   | 0004  |  B

أخيرا الذاتي الانضمام إلى نقل ب القيم التالية إلى القيم.

هذا يبدو أن يكون عملية طويلة ينضب للحصول على ما أريد.حتى أنا بعد المشورة بشأن ما إذا كان أنا نسلك الطريق الصحيح أم أن هناك نهج آخر أن لدي أكثر بدا من شأنها أن تجعل الحياة أسهل بكثير.

ملاحظة 1) الحل يجب أن يكون في T-SQL على MSSQL 2005.

ملاحظة 2) تنسيق الجدول لا يمكن تغييرها.

تحرير طريقة أخرى كنت قد فكرت يستخدم الاتحادات الفردية مبلغ()s على كل عمود:

SELECT '0001' as Index, SUM(A0001) as A, SUM(B0001) as B FROM TABLE
UNION
SELECT '0002' as Index, SUM(A0002) as A, SUM(B0002) as B FROM TABLE
UNION
SELECT '0003' as Index, SUM(A0003) as A, SUM(B0003) as B FROM TABLE
UNION
SELECT '0004' as Index, SUM(A0004) as A, SUM(B0004) as B FROM TABLE
UNION
...

ولكن هذا النهج لا تبدو لطيفة جدا إما

تحرير حتى الآن هناك 2 ردود فعل كبيرة.ولكن أود أن إضافة اثنين من أكثر شروط الاستعلام :-)

1) لا تحتاج إلى تحديد الصفوف على أساس مجموعة من الطوابع الزمنية (minv < الطابع الزمني < maxv).

2) أنا أيضا بحاجة إلى مشروط حدد الصفوف على UDF أن عمليات الزمني

باستخدام Brettski الجدول أسماء قد سبق تترجم إلى:

...
(SELECT A0001, A0002, A0003, B0001, B0002, B0003 
 FROM ptest 
 WHERE timestamp>minv AND timestamp<maxv AND fn(timestamp)=fnv) p
unpivot
(val for item in (A0001, A0002, A0003, B0001, B0002, B0003)) as unpvt
...

بالنظر إلى أن كنت قد مشروط إضافة fn() المطلب ، أعتقد أنني أيضا بحاجة للذهاب إلى SQL ديناميكية المسار المقترح من قبل جوناثان.خصوصا علي بناء نفس الاستعلام عن 12 جداول مختلفة - كل من نفس الطراز.

هل كانت مفيدة؟

المحلول

نفس كيندا الجواب هنا في هذا المتعة لعبة:

-- Get column names from system table
DECLARE @phCols NVARCHAR(2000)
SELECT @phCols = COALESCE(@phCols + ',[' + name + ']', '[' + name + ']') 
    FROM syscolumns WHERE id = (select id from sysobjects where name = 'Test' and type='U')

-- Get rid of the column we don't want
SELECT @phCols = REPLACE(@phCols, '[Timestamp],', '')

-- Query & sum using the dynamic column names
DECLARE @exec nvarchar(2000)
SELECT @exec =
'
    select
        SUBSTRING([Value], 2, LEN([Value]) - 1) as [Index],
        SUM(CASE WHEN (LEFT([Value], 1) = ''A'') THEN Cols ELSE 0 END) as AValue, 
        SUM(CASE WHEN (LEFT([Value], 1) = ''B'') THEN Cols ELSE 0 END) as BValue
    FROM
    (
        select *
        from (select ' + @phCols + ' from Test) as t
        unpivot (Cols FOR [Value] in (' + @phCols + ')) as p
    ) _temp
    GROUP BY SUBSTRING([Value], 2, LEN([Value]) - 1)
'
EXECUTE(@exec)

أنت لا تحتاج إلى رمز القرص الثابت أسماء الأعمدة في هذا واحد.

نصائح أخرى

حسنا, لقد حان حتى مع حل واحد والتي ينبغي أن تبدأ.فإنه من المحتمل أن يستغرق بعض الوقت لوضع معا, ولكن سوف تؤدي بشكل جيد.سيكون من الجميل إذا لم يكن لديك قائمة من جميع الأعمدة حسب الاسم.

أساسا هذا هو استخدام UNPIVOT و وضع هذا المنتج في الجدول المؤقت ، ثم الاستعلام إلى النهائي الخاص بك مجموعة البيانات.سميت طاولتي ptest عندما وضع هذا معا, هذا هو واحد مع كل من A0001 ، الخ الأعمدة.

-- Create the temp table
CREATE TABLE #s (item nvarchar(10), val int)

-- Insert UNPIVOT product into the temp table
INSERT INTO  #s (item, val)
SELECT item, val
FROM
(SELECT A0001, A0002, A0003, B0001, B0002, B0003
FROM ptest) p
unpivot
(val for item in (A0001, A0002, A0003, B0001, B0002, B0003)) as unpvt

-- Query the temp table to get final data set
SELECT RIGHT(item, 4) as item1,
Sum(CASE WHEN LEFT(item, 1) = 'A' THEN val ELSE 0 END) as A,
Sum(CASE WHEN LEFT(item, 1) = 'B' THEN val ELSE 0 END) as B
from #s
GROUP BY RIGHT(item, 4)

-- Delete temp table 
drop table #s

بالمناسبة شكرا على السؤال, كان هذا هو أول الوقت كنت حصلت على استخدام UNPIVOT.أردت دائما أن فقط لم يكن هناك حاجة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top