سؤال

لدي مشكلة بسيطة للغاية وتتطلب حلاً سريعًا وبسيطًا للغاية في SQL Server 2005.

لدي جدول به x من الأعمدة.أريد أن أكون قادرًا على تحديد صف واحد من الجدول ثم تحويل الأعمدة إلى صفوف.

TableA
Column1, Column2, Column3

بيان SQL لruturn

ResultA
Value of Column1
Value of Column2
Value of Column3

@كيفن: لقد أجريت بحثًا على Google حول هذا الموضوع ولكن هناك الكثير من الأمثلة التي كانت معقدة للغاية بالنسبة لمثالي، هل أنت قادر على المساعدة أكثر؟

@ماريو:يحتوي الحل الذي أقوم بإنشائه على 10 أعمدة تخزن القيم من 0 إلى 6 ويجب أن أعرف عدد الأعمدة التي لها القيمة 3 أو أكثر.لذلك فكرت في إنشاء استعلام لتحويل ذلك إلى صفوف ثم استخدام الجدول الذي تم إنشاؤه في استعلام فرعي لأقول حساب عدد الصفوف ذات العمود > = 3

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

المحلول

يجب عليك إلقاء نظرة على جملة UNPIVOT.

تحديث1:GateKiller، من الغريب أنني قرأت مقالًا (حول شيء غير ذي صلة) حول هذا الموضوع هذا الصباح وأحاول تنشيط ذاكرتي حيث رأيته مرة أخرى، وكان لدي بعض الأمثلة اللائقة أيضًا.سوف يعود لي أنا متأكد.

تحديث2:وجدته: http://weblogs.sqlteam.com/jeffs/archive/2008/04/23/unpivot.aspx

نصائح أخرى

كان علي أن أفعل هذا لمشروع من قبل.إحدى الصعوبات الرئيسية التي واجهتني هي شرح ما كنت أحاول القيام به للآخرين.لقد أمضيت الكثير من الوقت في محاولة القيام بذلك في SQL، لكنني وجدت أن الوظيفة المحورية غير كافية على الإطلاق.لا أتذكر السبب الدقيق لذلك، ولكنه بسيط للغاية بالنسبة لمعظم التطبيقات، ولم يتم تنفيذه بالكامل في MS SQL 2000.انتهيت من كتابة وظيفة محورية في .NET.سأنشرها هنا على أمل أن تساعد شخصًا ما في يوم من الأيام.

 ''' <summary>
    ''' Pivots a data table from rows to columns
    ''' </summary>
    ''' <param name="dtOriginal">The data table to be transformed</param>
    ''' <param name="strKeyColumn">The name of the column that identifies each row</param>
    ''' <param name="strNameColumn">The name of the column with the values to be transformed from rows to columns</param>
    ''' <param name="strValueColumn">The name of the column with the values to pivot into the new columns</param>
    ''' <returns>The transformed data table</returns>
    ''' <remarks></remarks>
    Public Shared Function PivotTable(ByVal dtOriginal As DataTable, ByVal strKeyColumn As String, ByVal strNameColumn As String, ByVal strValueColumn As String) As DataTable
        Dim dtReturn As DataTable
        Dim drReturn As DataRow
        Dim strLastKey As String = String.Empty
        Dim blnFirstRow As Boolean = True

        ' copy the original data table and remove the name and value columns
        dtReturn = dtOriginal.Clone
        dtReturn.Columns.Remove(strNameColumn)
        dtReturn.Columns.Remove(strValueColumn)

        ' create a new row for the new data table
        drReturn = dtReturn.NewRow

        ' Fill the new data table with data from the original table
        For Each drOriginal As DataRow In dtOriginal.Rows

            ' Determine if a new row needs to be started
            If drOriginal(strKeyColumn).ToString <> strLastKey Then

                ' If this is not the first row, the previous row needs to be added to the new data table
                If Not blnFirstRow Then
                    dtReturn.Rows.Add(drReturn)
                End If

                blnFirstRow = False
                drReturn = dtReturn.NewRow

                ' Add all non-pivot column values to the new row
                For Each dcOriginal As DataColumn In dtOriginal.Columns
                    If dcOriginal.ColumnName <> strNameColumn AndAlso dcOriginal.ColumnName <> strValueColumn Then
                        drReturn(dcOriginal.ColumnName.ToLower) = drOriginal(dcOriginal.ColumnName.ToLower)
                    End If
                Next
                strLastKey = drOriginal(strKeyColumn).ToString
            End If

            ' Add new columns if needed and then assign the pivot values to the proper column
            If Not dtReturn.Columns.Contains(drOriginal(strNameColumn).ToString) Then
                dtReturn.Columns.Add(drOriginal(strNameColumn).ToString, drOriginal(strValueColumn).GetType)
            End If
            drReturn(drOriginal(strNameColumn).ToString) = drOriginal(strValueColumn)
        Next

        ' Add the final row to the new data table
        dtReturn.Rows.Add(drReturn)

        ' Return the transformed data table
        Return dtReturn
    End Function

اتحاد ينبغي أن يكون صديقك:

SELECT Column1 FROM table WHERE idColumn = 1
UNION ALL
SELECT Column2 FROM table WHERE idColumn = 1
UNION ALL
SELECT Column3 FROM table WHERE idColumn = 1

ولكن يمكن يكون أيضا عدوك على مجموعات النتائج الكبيرة.

إذا كان لديك مجموعة ثابتة من الأعمدة وتعرف ماهيتها، فيمكنك إجراء سلسلة من التحديدات الفرعية بشكل أساسي

(SELECT Column1 AS ResultA FROM TableA) as R1

والانضمام إلى التحديدات الفرعية.كل هذا في استعلام واحد.

لست متأكدًا من بناء جملة SQL Server لهذا ولكن في MySQL سأفعل ذلك

SELECT IDColumn, ( IF( Column1 >= 3, 1, 0 ) + IF( Column2 >= 3, 1, 0 ) + IF( Column3 >= 3, 1, 0 ) + ... [snip ] )
  AS NumberOfColumnsGreaterThanThree
FROM TableA;

يحرر:يخبرني بحث Google الموجز (جدًا) أن CASE البيان يفعل ما أفعله مع IF بيان في MySQL.قد تستفيد أو لا تستفيد منها نتيجة جوجل وجدت

مزيد من التعديل:يجب أن أشير أيضًا إلى أن هذه ليست إجابة لسؤالك ولكنها حل بديل لمشكلتك الفعلية.

SELECT IDColumn, 
       NumberOfColumnsGreaterThanThree = (CASE WHEN Column1 >= 3 THEN 1 ELSE 0 END) + 
                                         (CASE WHEN Column2 >= 3 THEN 1 ELSE 0 END) + 
                                         (Case WHEN Column3 >= 3 THEN 1 ELSE 0 END) 
FROM TableA;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top