12
votes

SQL Server: Ordre par sous-requier avec Union

J'ai deux questions combinées à un Union tout 1 : xxx

xxx

Les deux, bien sûr, fonctionnent bien séparément, mais lorsqu'il est combiné avec un «code> union : xxx

La requête échoue avec l'erreur:

msg 104, niveau 15, état 1, ligne 3
La commande par les éléments doit apparaître dans la liste Sélectionner si l'instruction contient un opérateur syndical.

Comment puis-je utiliser une commande par une déclaration avec un syndicat tout?

Exemple-pâte-pâte xxx blockquote>

serveur: msg 104, niveau 15, état 1, ligne 2
La commande par les éléments doit apparaître dans la liste Sélectionner si l'instruction contient un opérateur syndical.

Notes de bas de page


7 commentaires

Votre exemple fonctionne pour moi dans SQL Server 2005 Même si je définis la base de données sur le mode de compatibilité SQL2000.


Regarde bien pour moi. Je me demande s'il y avait une restriction ou un bug étrange dans SQL Server 2000? Je ne me souviens pas, mais bon, ça fait presque une décennie ...


Il y a d'autres moyens d'écrire cette requête. Essayez-vous simplement de résoudre ce problème spécifique ou ne voulez-vous que des solutions qui vous permettent d'utiliser la sous-requête?


@Martin: Je peux dupliquer le problème sur une nouvelle instance SQL 2000.


@Tom H. Je suis parfaitement prêt à laisser quelqu'un d'autre faire le travail et réécrire la requête. Gardez à l'esprit que la vraie requête qui a déclenché cette question est beaucoup plus compliquée - ce qui le rend beaucoup plus difficile à convertir. Réécriture certainement la requête sera une réponse élueillonnée que d'autres personnes ayant le même problème pourraient être capables de le faire (et peut-être pouvons-nous également utiliser). Mais il semble que la réponse valide va avoir à dire: " Ceci est un bogue dans l'optimiseur de SQL Server 2000, qui a été corrigé en 2005. Et votre seul moyen de le contourner est de ré-écrire la requête. ".


En fait, mettez cette déclaration exacte, avec votre ré-écriture et vous avez une réponse acceptée.


On dirait que vous êtes peut-être en cours d'exécution: Connect.Microsoft.com/sqlserver/feedback/Détails/421924/... <- Développez les détails. Ce n'est pas beaucoup d'aide, je ne pense pas, mais cela peut au moins confirmer que c'est un bogue avec 2000 que MS n'a jamais été corrigé, alors les patchs et les packs de services ne vont pas aider.


4 Réponses :


1
votes

Je sais que vous pouvez utiliser un CTE (expression de table commune), où vous pouvez utiliser votre commande par la CTE.

;with results as
(

    SELECT Cassettes.CassetteNumber,
    LastCassetteTransfers.Amount,
    CassetteTransfers.CreatedDate
    FROM Cassettes
    INNER JOIN LastCassetteTransfers
    ON Cassettes.CassetteGUID = LastCassetteTransfers.CassetteGUID

    UNION ALL

    SELECT Cassettes.CassetteNumber,
    (
       SELECT TOP 1 CassetteTransfers.Amount
       FROM CassetteTransfers
       WHERE CassetteTransfers.CassetteGUID = Cassettes.CassetteGUID
       AND CassetteTransfers.Mode = 'ctmLoad'
    ) AS Amount,
    CassetteTransfers.CreatedDate
    FROM Cassettes

)

SELECT CassetNumber, Amount
FROM results
ORDER BY CassetteTransfers.CreatedDate DESC, CassetteTransfers.Amount


1 commentaires

Il est sur SQL 2000. Aucun support CTE.



6
votes

Un peu de hack, mais cela fonctionnera.

CREATE TABLE Friends (Flavor int, Color int)
CREATE TABLE Strangers (Flavor int, StrangerID int)
CREATE TABLE Rainbows (StrangerID int, Color int, Wavelength int)
go

SELECT Flavor, Color
FROM Friends

UNION ALL

SELECT Flavor,
    (SELECT Color FROM 
        (SELECT TOP 1 Color, Wavelength
         FROM Rainbows
         WHERE Rainbows.StrangerID = Strangers.StrangerID
         ORDER BY Wavelength DESC
         ) AS Foo
    ) AS Color
FROM Strangers
go

DROP TABLE Rainbows
DROP TABLE Strangers
DROP TABLE Friends


0 commentaires

1
votes

En réalité, en regardant la solution de contournement de ce lien que j'ai commenté, vous voudrez peut-être essayer ceci: xxx

... ou un type similaire de chose à essayer de tromper le moteur à ne pas Se plaindre.

Mais je ne peux pas le tester, j'ai peur; Je ne pense pas que nous avons une boîte de 2000 à gauche dans le bâtiment, virtuelle ou autrement.

EDIT: AH! Ressemble à Joe et j'ai chevauché sur notre snapisme :)


0 commentaires

0
votes

Je suggère de créer une table variable dans le format des colonnes que vous souhaitez.

  1. Exécutez la requête d'insertion du tableau d'origine dans une table variable pour chaque table vous qui rejoints, y compris tous les filtres et trier que vous voulez appliquer. li>
  2. renvoie la table de variable li> ol>

    Exemple: P>

    set nocount on
    DECLARE @temp_table TABLE(Flavor varchar(20), Color varchar(20))
        
        insert into @temp_table (Flavor,Color)
        /*Apply select query #1 with all filters, joins and sorting */
        SELECT Flavor,Color   FROM Strangers  ORDER BY Wavelength DESC
        
        insert into @temp_table (Flavor,Color)
        /*Apply select query #2 with all filters, joins and sorting */
        SELECT Flavor, Color FROM Friends
        
        /*Return the results pushed into @variable table */
        select * from @temp_table
    


0 commentaires