错误:子查询返回的值超过1

时间:2012-12-17 15:51:52

标签: sql sql-server subquery

我得到的完整错误是:

  

Msg 512,Level 16,State 1,Line 1
  子查询返回的值超过1。当子查询遵循=,!=,<,< =,>,> =或子查询用作表达式时,不允许这样做。

我过去曾经使用过的SQL代码通过了,我需要修复它,但是我得到了上面的错误,但即使我注释掉某些部分,错误仍然保持不变

这是sql代码:

SELECT  
    OrderId = OrdNameAdd.ORDERS_ID,
    LTRIM(ISNULL(OrdNameAdd.OBY_FirstName, '') + ' ' + ISNULL(OrdNameAdd.OBY_LASTNAME, '')) AS OrderedByName,
    ObyVar1 = (SELECT varfld_value FROM MAILERVBL WHERE OBYMAILER = MAILERVBL.MAILER_SEQID AND VARDEF_SEQUENCE = 1),
    ObyVar2 = (SELECT varfld_value FROM MAILERVBL WHERE OBYMAILER = MAILERVBL.MAILER_SEQID AND VARDEF_SEQUENCE = 2),
    ObyVar3 = (SELECT varfld_value FROM MAILERVBL WHERE OBYMAILER = MAILERVBL.MAILER_SEQID AND VARDEF_SEQUENCE = 3),
    ExtendedDefaultValue = (SELECT sum(isnull(p.prduct_value,0) *  (isnull(pickdt.prdord_toshipqty,1))) 
                            FROM PICKDT 
                            LEFT OUTER JOIN 
                               locVerBals ON PICKDT.PRVERS_SEQID = locVerBals.PRVERS_Seqid 
                            LEFT OUTER JOIN 
                               LOCPRDSUM p ON locVerBals.PRDUCT_Seqid = p.PRDUCT_SEQID 
                                           AND p.system_id = PICPAK.SYSTEM_ID 
                            WHERE
                               PICKDT.PICPAK_Seqid = PICPAK.PICPAK_Seqid 
                               AND p.PRDUCT_INACTIVEDATE IS NULL), 
    FulfCharges = (rpt_BD.Linesshipped * ACCDEF_ChargePerLine) + ACCDEF_ChargePerShipment, 
    PubFreight = (rpt_BD.PubFreight), 
    TotalValue = 
        (SELECT 
            sum(isnull(p.prduct_value, 0) * (isnull(pickdt.prdord_toshipqty, 1))) 
         from PICKDT 
         LEFT OUTER JOIN locVerBals ON PICKDT.PRVERS_SEQID = locVerBals.PRVERS_Seqid 
         LEFT OUTER JOIN LOCPRDSUM p ON locVerBals.PRDUCT_Seqid = p.PRDUCT_SEQID 
                                     AND p.system_id = PICPAK.SYSTEM_ID 
         WHERE 
             PICKDT.PICPAK_Seqid = PICPAK.PICPAK_Seqid AND p.PRDUCT_INACTIVEDATE IS NULL) 
         + isnull((rpt_BD.Linesshipped * ACCDEF_ChargePerLine), 0) 
         + isnull(ACCDEF_ChargePerShipment,0) + isnull((rpt_BD.PubFreight), 0)
FROM 
    PICPAK 
LEFT OUTER JOIN 
    ORDSTO ON PICPAK.ORDSTO_Seqid = ORDSTO.ORDSTO_Seqid 
LEFT OUTER JOIN 
    OrdNameAdd ON ORDSTO.ORDERS_Seqid = OrdNameAdd.ORDERS_SEQID 
LEFT OUTER JOIN 
    Rpt_BillingDetail rpt_BD ON PICPAK.PICPAK_Seqid = rpt_BD.PICPAK_Seqid 

---------------hERE
WHERE 
    (convert(datetime, DateShipped, 1) >= '4/17/2012' 
     AND convert(datetime, DateShipped, 1) <= '12/17/2012')
---------------HERE

    AND (PICPAK.PICPAK_Status = 'Complete' OR PICPAK.PICPAK_Status = 'Shipped' 
         OR picpak_Status = 'Voided') 
    /*AND (p.PRDUCT_INACTIVEDATE IS NULL)*/
    AND ISNULL(PICPAK.SUPPLR_SEQID,0) = 0
GROUP BY
    OrdNameAdd.ORDERS_ID,
    OrdNameAdd.OBY_FirstName,
    OrdNameAdd.OBY_LASTNAME,
    OrdNameAdd.obymailer,
    PICPAK.PICPAK_Seqid,
    PICPAK.System_Id,
    rpt_BD.PubFreight,
    ACCDEF_ChargePerLine,
    ACCDEF_ChargePerShipment,
    rpt_BD.Linesshipped,
    rpt_BD.Numpackages,
    ordsto.orders_seqid
ORDER BY
    ordsto.orders_seqid ASC

5 个答案:

答案 0 :(得分:2)

我建议你分别执行每个子查询以找出哪一个返回多个记录

答案 1 :(得分:1)

如果您对SELECT columns Ex: (1)WHERE col = cluses Ex:(2)进行子查询,则应确保只返回一个值。

--Ex:(1) make sure only one row returned by the sub query, 
--this case can be voided using TOP 1 from the sub query
SELECT col1, (SELECT colX from Table2 ) 
FROM Table1

--Ex:(2) this case can be avoided using IN instead =
SELECT col1, col2
FROM Table1
WHERE col3 = (SELECT colX from Table2 ) 

答案 2 :(得分:1)

在您的查询中,您有五个子查询用于ObyVar1,ObyVar2,ObyVar3,ExtendedDefaultValue和TotalValue。

两个值子查询使用的聚合没有group by,所以它们应该返回一个值。

你的问题出在三个ObyVars中。

有两种方法可以解决这个问题:

  1. 汇总值。 max(varfld_value)
  2. 也是如此
  3. 选择一个值。在SQL Server中,这将是top 1(在其他数据库中,它可能是rownum = 1limit 1)。
  4. 但总的来说,我发现select语句中的select语句是不受欢迎的。我会用from子句中的子查询替换这三个变量:

    (select mailer_seqid,
            max(case when vardef_sequence = 1 then varfld_value end) as vv_1, 
            max(case when vardef_sequence = 2 then varfld_value end) as vv_2,
            max(case when vardef_sequence = 3 then varfld_value end) as vv_3
     from mailervbl
     group by mailer_seqid
    )
    

    在大多数情况下,这应该比三个子查询更高效。

答案 3 :(得分:0)

我们似乎没有办法在没有访问你的数据库的情况下识别它们,不建议写任何这样的where语句,不仅仅是谈论性能,还要讨论你现在面临的问题。

要解决此问题,您需要完成整个逻辑并在没有子查询的情况下重写它,或者查看是否可以在子查询中通过DISTINCT / TOP 1过滤掉一些数据,而不会破坏逻辑本身。我建议你改写它,有时听起来很复杂,但事情会变得简单。

答案 4 :(得分:0)

您不能从您正在执行单个SUM语句的子查询中获取副本,因此问题是针对MAILERVBL表。

如果您一直在寻找重复项,请运行以下类型的代码来识别重复项:

select MAILER_SEQID, VARDEF_SEQUENCE, count(*) as numentries
from MAILERVBL 
group by MAILER_SEQID, VARDEF_SEQUENCE
having count(*) > 1
order by numentries desc -- not really needed but useful to see where most of your duplicates are

根据条款,在选择组中放置您希望唯一的列。