4

次のようなクエリがあります。

DECLARE @razem VARCHAR(MAX);

SELECT  Ordering.orderID , 
        Document.number, 
        (User_info.name  +' '+ User_info.surname),   
        Ordering.dateStart, 
        Ordering.dateEnd ,   
        (
            select   COALESCE(' ',@razem)+sell_type.name as r  
            from    Ordering_sell_type, Sell_type 
            where   orderID = Ordering.orderID and 
                    Ordering_sell_type.sell_typeID = sell_type.sell_typeID
        ) podz
FROM    Ordering, User_info, Product_Document, Document, Document_type   
WHERE   Ordering.orderID = Product_document.orderID  
        AND Document.documentID = Document_type.documentID  
        AND Document.documentID = Product_document.documentID  
        AND  Ordering.userID = User_info.userID   
        AND Ordering.isClosed = 1 AND Document_type.typeID = 1   
GROUP   BY  Document.isitfiscal, Document.refDocID, 
            Document.number, Ordering.orderID, User_info.name, 
            User_info.surname, Ordering.dateStart, 
            Ordering.dateEnd , Ordering.isCLosed  
ORDER   BY Ordering.dateEnd

そして、その COALESCE 関数では、選択した注文のすべての支払いタイプを取得したいと考えています。たとえば、orderID 123 には payTypes = Card、Cash、orderID には payTypes = Cash があります。

問題は、次のようなメイン クエリの最後の行として 1 つの単純な行に入れたいことです。エラーが発生しました:

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

複数の行を返すためです。サブクエリで有料タイプを取得し、1 つの文字列として返すことは可能ですか?

4

3 に答える 3

5

使用した構文に基づいて、SQL-Server を使用していると想定しているため、SQL-Server の XML 拡張機能を使用して文字列を連結できます。

SELECT  Ordering.orderID, 
        Document.number, 
        [UserName] = User_info.name  +' '+ User_info.surname,   
        Ordering.dateStart, 
        Ordering.dateEnd,
        [podz] = STUFF((    SELECT  DISTINCT ' ' + SellType.Name
                            FROM    Ordering_Sell_Type
                                    INNER JOIN Sell_Type
                                        ON Sell_Type.sell_typeID = Ordering_Sell_Type.sell_typeID
                            WHERE   Ordering.OrderID = Ordering_SellType.OrderId
                            FOR XML PATH(''), TYPE
                        ).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
FROM    Ordering
        INNER JOIN User_Info
            ON Ordering.UserID = User_Info.UserID
        INNER JOIN ProductDocument
            ON Ordering.OrderID = Product_Document.OrderID
        INNER JOIN Document
            ON Document.DocumentID = Product_Document.DocumentID
        INNER JOIN Document_Type
            ON Document_Type.DocumentID = Document.DocumentID
WHERE   Ordering.IsClosed = 1
AND     Document_Type.TypeID = 1
ORDER BY Ordering.dateEnd;

ANSI 89 のすべての結合を ANSI 92 に置き換えたことに注意してください。これはより現代的な構文であり、より読みやすいオプションとして一般的に受け入れられています (もちろん個人的な好みであり、まだいくつかのケースがあるため、一般的に受け入れられていると言います)。 Oracle は ANSI89 結合をより適切に最適化します)。

編集

重複が Product_Document テーブルからのものであるデータを確認したら、これを使用してこれらを削除できます。

SELECT  Ordering.orderID, 
        Document.number, 
        [UserName] = User_info.name  +' '+ User_info.surname,   
        Ordering.dateStart, 
        Ordering.dateEnd,
        [podz] = STUFF((    SELECT  DISTINCT ' ' + SellType.Name
                            FROM    Ordering_Sell_Type
                                    INNER JOIN Sell_Type
                                        ON Sell_Type.sell_typeID = Ordering_Sell_Type.sell_typeID
                            WHERE   Ordering.OrderID = Ordering_SellType.OrderId
                            FOR XML PATH(''), TYPE
                        ).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
FROM    Ordering
        INNER JOIN User_Info
            ON Ordering.UserID = User_Info.UserID
        INNER JOIN 
        (   SELECT  DISTINCT OrderID, DocumentID
            FROM    Product_Document
        ) Product_Document
            ON Ordering.OrderID = Product_Document.OrderID
        INNER JOIN Document
            ON Document.DocumentID = Product_Document.DocumentID
        INNER JOIN Document_Type
            ON Document_Type.DocumentID = Document.DocumentID
WHERE   Ordering.IsClosed = 1
AND     Document_Type.TypeID = 1
ORDER BY Ordering.dateEnd;
于 2013-02-26T13:54:18.860 に答える
0

このSOの記事/回答は、 https://stackoverflow.com/a/2410524/283895について話しているように、一連のvarchar行を単一の列にロールアップ/集約するためのさまざまなアプローチについて議論するのに適しています

于 2013-02-26T13:56:33.673 に答える
0

はい。ただし、使用する RDBMS によって異なります。

1 行にデータのリストを生成するには、使用している RDBMS に固有の分析関数を使用するか、独自の関数を作成する必要があります。

Oracle の場合: WM_CONCAT、LISTAGG、または XMLAGG 関数は、同様のデータを共有する複数の行をリストに変換します。

Coalese は一度に 1 つの行のみを処理し、行を結合しません。

  • ORACLE: WM_CONCAT、LISTAGG、XMLAGG
  • SQL サーバー: XML パス
  • 私のSQL:Group_Concat

使用/構文は異なります。そのため、RDBMS に応じてこれらの用語を検索することをお勧めします。

于 2013-02-26T13:59:26.820 に答える