2012-12-17 190 views
0

完整的错误我得到的是:错误:子查询返回多个值

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

我被那在过去使用来解决这个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 
+3

它可能是3个'SELECT varfld_value'子查询之一。分别执行它们中的每一个以查看哪一个返回多行。看起来其他子查询都是非分组聚合('sum()'),所以这些应该只返回一行。 –

+0

注释掉'ObyVar_n_'行并尝试运行查询,然后逐行添加一行。这可能会识别导致问题的代码。解决这个问题可能需要添加适当的WHERE子句以确保返回单个行,并添加聚集,例如, MAX()“,或者在更大的范围内重新考虑设计。 – HABO

回答

1

在您的查询,你有ObyVar1,ObyVar2,ObyVar3,ExtendedDefaultValue和总价值5子查询。

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

你的问题在三个ObyVars。

有简单的两种方式来摆脱这样的:

  1. 聚合值。那么max(varfld_value)
  2. 选择一个值。在SQL Server中,这将是top 1(在其他数据库中,它可能是rownum = 1limit 1)。

但总的来说,我发现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 
) 

在大多数情况下,这应该是作为或比三子查询更为有效。

+0

这就是它的人......我增加了最大的选择,它的工作。后来我发现即使应该只有一条匹配子查询的记录,当他们更新软件时,他们会插入一些与子查询匹配的空值,所以MAX不仅能够正常工作,而且能够做到应该做的确切工作。 – Nathan

2

我会建议您单独执行每个子查询,找出哪一个是返回不止一个记录rd

0

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

要解决这个问题,您需要通过完整的逻辑并重写它,而不需要子查询,或者查看是否可以通过子查询中的DISTINCT/TOP 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) 
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 

认沽取列您期望在这两个你选择唯一组由条款。