2012-12-17 141 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 

認沽取列您期望在這兩個你選擇唯一組由條款。