ไม่สามารถผูกตัวระบุหลายส่วนได้


196

ฉันเห็นข้อผิดพลาดที่คล้ายกันใน SO แต่ฉันไม่พบวิธีแก้ไขปัญหาของฉัน ฉันมีแบบสอบถาม SQL เช่น:

SELECT DISTINCT
        a.maxa ,
        b.mahuyen ,
        a.tenxa ,
        b.tenhuyen ,
        ISNULL(dkcd.tong, 0) AS tongdkcd
FROM    phuongxa a ,
        quanhuyen b
        LEFT OUTER JOIN ( SELECT    maxa ,
                                    COUNT(*) AS tong
                          FROM      khaosat
                          WHERE     CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                                              AND
                                                              'Sep 5 2011'
                          GROUP BY  maxa
                        ) AS dkcd ON dkcd.maxa = a.maxa
WHERE   a.maxa <> '99'
        AND LEFT(a.maxa, 2) = b.mahuyen
ORDER BY maxa;

เมื่อฉันเรียกใช้คิวรีนี้ผลลัพธ์ข้อผิดพลาดคือ: ตัวระบุหลายส่วน "a.maxa" ไม่สามารถผูกได้ ทำไม?
P / s: ถ้าฉันแบ่งแบบสอบถามเป็น 2 แบบสอบถามแต่ละมันก็โอเค

SELECT DISTINCT
        a.maxa ,
        b.mahuyen ,
        a.tenxa ,
        b.tenhuyen
FROM    phuongxa a ,
        quanhuyen b
WHERE   a.maxa <> '99'
        AND LEFT(a.maxa, 2) = b.mahuyen
ORDER BY maxa;

และ

SELECT  maxa ,
        COUNT(*) AS tong
FROM    khaosat
WHERE   CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                        AND     'Sep 5 2011'
GROUP BY maxa;

ที่ไม่phuongxaตารางใส่คอลัมน์maxa?
Michael Petrotta

1
จะเกิดอะไรขึ้นถ้าคุณเพิ่มกลุ่มโดย maxa, tong - ทันทีหลังจาก 5 ก.ย. 2011
user710502

ใช่มันมี ถ้าฉันแบ่งแบบสอบถามเป็น 2 แบบสอบถามย่อยมันก็โอเค
PhamMinh

ดูเหมือนว่าคุณกำลังดำเนินการกับฐานข้อมูลผิด เพิ่มคำสั่ง "USE [ชื่อฐานข้อมูล]" ไปที่จุดเริ่มต้นของแบบสอบถามและดูว่าคุณยังได้รับข้อผิดพลาดหรือไม่
ไบรอัน

1
ไม่ฉันได้กล่าวไว้ข้างต้นถ้าฉันแบ่งแบบสอบถามออกเป็น 2 แบบสอบถามแต่ละรายการก็จะทำงานได้ดี
PhamMinh

คำตอบ:


226

คุณกำลังผสมการเข้าร่วมโดยนัยกับการรวมที่ชัดเจน ที่ได้รับอนุญาต แต่คุณต้องระวังวิธีการทำอย่างถูกต้อง

สิ่งที่เกิดขึ้นคือการรวมอย่างชัดเจน (สิ่งที่นำมาใช้โดยใช้JOINคำสำคัญ) มีความสำคัญมากกว่าคำที่มีความหมาย (การรวมของ 'เครื่องหมายจุลภาค' โดยที่เงื่อนไขการเข้าร่วมถูกระบุไว้ในWHEREข้อ)

นี่คือโครงร่างของแบบสอบถามของคุณ:

SELECT
  
FROM a, b LEFT JOIN dkcd ON 
WHERE 

คุณอาจคาดหวังว่ามันจะทำตัวแบบนี้:

SELECT
  
FROM (a, b) LEFT JOIN dkcd ON 
WHERE 

นั่นคือการรวมกันของตารางaและจะเข้าร่วมกับโต๊ะb dkcdในความเป็นจริงสิ่งที่เกิดขึ้นคือ

SELECT
  
FROM a, (b LEFT JOIN dkcd ON …)
WHERE 

นั่นคือตามที่คุณอาจเข้าใจแล้วdkcdจะเข้าร่วมเฉพาะbและต่อต้านเท่านั้นbผลลัพธ์ของการเข้าร่วมจะถูกรวมเข้ากับaและกรองเพิ่มเติมกับWHEREข้อ ในกรณีนี้การอ้างอิงใด ๆaในส่วนONคำสั่งไม่ถูกต้องไม่aเป็นที่รู้จัก ณ จุดนั้น นั่นคือเหตุผลที่คุณได้รับข้อความแสดงข้อผิดพลาด

หากฉันเป็นคุณฉันอาจลองเขียนแบบสอบถามนี้ใหม่และวิธีแก้ปัญหาหนึ่งที่อาจเป็นไปได้:

SELECT DISTINCT
  a.maxa,
  b.mahuyen,
  a.tenxa,
  b.tenhuyen,
  ISNULL(dkcd.tong, 0) AS tongdkcd
FROM phuongxa a
  INNER JOIN quanhuyen b ON LEFT(a.maxa, 2) = b.mahuyen
  LEFT OUTER JOIN (
    SELECT
      maxa,
      COUNT(*) AS tong
    FROM khaosat
    WHERE CONVERT(datetime, ngaylap, 103) BETWEEN 'Sep 1 2011' AND 'Sep 5 2011'
    GROUP BY maxa
  ) AS dkcd ON dkcd.maxa = a.maxa
WHERE a.maxa <> '99'
ORDER BY a.maxa

ที่นี่ตารางaและจะเข้าร่วมเป็นครั้งแรกแล้วผลจะเข้าร่วมb dkcdโดยทั่วไปนี่เป็นข้อความค้นหาเดียวกับของคุณเพียงใช้ไวยากรณ์ที่แตกต่างกันสำหรับหนึ่งในการรวมซึ่งสร้างความแตกต่างอย่างมาก: การอ้างอิงa.maxaในdkcdเงื่อนไขการเข้าร่วมของตอนนี้ใช้ได้จริง ๆ

ตามที่ @Aaron Bertrand ได้บันทึกไว้อย่างถูกต้องคุณควรมีสิทธิ์ได้รับmaxaชื่อแทนเฉพาะaในORDER BYประโยค


การสั่งซื้อโดย maxa ยังคงคลุมเครือใช่ไหม นอกจากนี้ฉันต้องระวังด้วย 'วันที่ 1 กันยายน 2011' จะไม่ทำงานกับการตั้งค่าภาษา / ภูมิภาคที่แตกต่างกัน
Aaron Bertrand

@Aaron: เห็นด้วยเกี่ยวกับORDER BY maxaขอบคุณ สำหรับวันที่ฉันเชื่อว่านั่นเป็นวิธีที่ OP เลือกให้ระบุในสภาพแวดล้อมของพวกเขา
Andriy M

"เข้าร่วมอย่างชัดเจน ... มีความสำคัญมากกว่าคนที่มีความหมายโดยนัย" - คุณช่วยอ้างอิงได้ไหมได้ไหม เช่นนั้นกำหนดไว้ในมาตรฐาน SQL หรือมันเป็นคุณสมบัติของผลิตภัณฑ์? ขอบคุณ
oneday

1
@onedaywhen: ฉันเกรงว่านี่จะไม่ได้เป็นเพียงการสังเกตในด้านของฉัน ฉันค่อนข้างโล่งใจกับความจริงที่ว่าฉันไม่ใช่คนแรกที่พูดถึงความสำคัญของการเข้าร่วมที่นี่ แต่นอกเหนือจากนั้นฉันยินดีที่จะพบการยืนยันอย่างเป็นทางการทุกชนิดด้วยตัวเอง
Andriy M

1
ในกรณีของฉันฉันลืมใส่ช่องว่างเมื่อฉันเชื่อมสตริงเพื่อสร้าง sql ดังนั้น 'FROM dbo.table_a a' + 'INNER JOIN dbo.table_b b' กลายเป็น 'FROM dbo.table_a aINNER JOIN dbo.table_b b' และมันสับสนและทำให้ฉันเกิดข้อผิดพลาดนี้ รายละเอียดรายละเอียดรายละเอียด
Guy Schalnat

40

บางครั้งข้อผิดพลาดนี้เกิดขึ้นเมื่อคุณใช้สคีมา (dbo) ในการค้นหาของคุณในทางที่ผิด

เช่นถ้าคุณเขียน:

select dbo.prd.name
from dbo.product prd

คุณจะได้รับข้อผิดพลาด

ในสถานการณ์นี้เปลี่ยนเป็น:

select prd.name
from dbo.product prd

1
อันนี้ค่อนข้างน่ารำคาญและเอาฉันไปนานเกินไปที่จะคิดออก Thanx ส่วนที่น่ารำคาญที่สุดคือบางครั้งมัน naggs เกี่ยวกับเรื่องนี้ แต่เวลาอื่น ๆ ผ่านมัน normaly
DanteTheSmith

12

หากคุณให้ alies เปลี่ยนชื่อเป็นชื่อจริง

ตัวอย่างเช่น

SELECT  
    A.name,A.date
  FROM [LoginInfo].[dbo].[TableA] as A
   join 
  [LoginInfo].[dbo].[TableA] as B 
  on  [LoginInfo].[dbo].[TableA].name=[LoginInfo].[dbo].[TableB].name;

เปลี่ยนเป็น

SELECT  
    A.name,A.date
  FROM [LoginInfo].[dbo].[TableA] as A
   join 
  [LoginInfo].[dbo].[TableA] as B 
  on  A.name=B.name;

1
นอกจากนี้หากคุณกำลังสร้างสตริง sql ให้ระวังช่องว่างท้ายท้ายบรรทัด มันแปลง alias M ของฉันเป็น MINNER เมื่อเข้าร่วมบรรทัด INNER JOIN ถัดไปด้านล่าง ผู้สร้างโปรไฟล์ SQL ที่แสดงการดำเนินการสตริงช่วยแก้ไขปัญหาของฉัน (แสดงความคิดเห็นที่นี่เนื่องจากมีความเกี่ยวข้องกับปัญหานามแฝง v จริง ๆ )
Simon

ว้าว @Simon ขอบคุณคุณฉันไม่ได้คิดเกี่ยวกับเรื่องนี้และกำลังต่อสู้กับกำแพงพยายามคิดออกว่าทำไมการค้นหาของฉันถึงไม่ทำงานฉันไม่มีที่ว่างในตอนท้ายของการรับส่งคืนสตริง!
buradd

9

ฉันกำลังดิ้นรนกับข้อความแสดงข้อผิดพลาดเดียวกันใน SQL Server เนื่องจากฉันมีการเชื่อมต่อหลายครั้งการเปลี่ยนลำดับการรวมได้แก้ไขให้ฉัน


3

ในกรณีของฉันปัญหากลายเป็นชื่อนามแฝงที่ฉันให้ไว้ในตาราง "oa" ดูเหมือนว่าจะไม่เป็นที่ยอมรับสำหรับ SQL Server


2

ฉันมีข้อผิดพลาดเดียวกันจาก JDBC ตรวจสอบทุกอย่างและแบบสอบถามของฉันไม่เป็นไร ปรากฎในข้อที่ฉันมีข้อโต้แย้ง:

where s.some_column = ?

และค่าของการโต้แย้งที่ฉันผ่านเป็นโมฆะ สิ่งนี้ยังให้ข้อผิดพลาดเดียวกันซึ่งทำให้เข้าใจผิดเพราะเมื่อคุณค้นหาอินเทอร์เน็ตคุณพบว่ามีบางอย่างผิดปกติกับโครงสร้างการสืบค้น แต่ไม่ใช่ในกรณีของฉัน แค่คิดว่าบางคนอาจประสบปัญหาเดียวกัน


2

สิ่งที่ใช้ได้ผลสำหรับฉันคือเปลี่ยนส่วนคำสั่ง WHERE ของฉันให้เป็นคิวรีย่อย SELECT

จาก:

    DELETE FROM CommentTag WHERE [dbo].CommentTag.NoteId = [dbo].FetchedTagTransferData.IssueId

ถึง:

    DELETE FROM CommentTag WHERE [dbo].CommentTag.NoteId = (SELECT NoteId FROM FetchedTagTransferData)

1

ฉันใหม่กับ SQL แต่เจอปัญหานี้ในหลักสูตรที่ฉันทำและพบว่าการกำหนดคิวรีให้กับโครงการนั้นช่วยกำจัดข้อผิดพลาดแบบหลายส่วนโดยเฉพาะ ตัวอย่างโครงการที่ฉันสร้างคือโครงการ CTU SQL ดังนั้นฉันจึงมั่นใจว่าฉันเริ่มต้นสคริปต์ด้วย USE [โครงการ CTU SQL] เป็นบรรทัดแรกของฉันตามด้านล่าง

USE [CTU SQL Project]
SELECT Advisors.First_Name, Advisors.Last_Name...and so on.

1
เมื่อคุณพูดว่า "โครงการ" ฉันถือว่าคุณหมายถึงฐานข้อมูลไม่ใช่การฉาย คำสั่งการใช้งานเพียงแค่เปลี่ยนฐานข้อมูลที่คุณกำหนดขอบเขตแบบสอบถามไว้
Charleh

ใช่โครงการ Charleh เช่นเดียวกับในฐานข้อมูลที่ฉันทำงานอยู่ ฉันไม่แน่ใจว่าสิ่งที่ฉันทำผิดกับฐานข้อมูลของฉัน แต่ระบุว่า "ใช้" และฐานข้อมูลเฉพาะเพื่อขอบเขตกำจัดข้อผิดพลาดของฉัน
Bogartz

1

หากข้อผิดพลาดนี้เกิดขึ้นในการUPDATEตรวจสอบอีกครั้งJOINบนตารางกับคอลัมน์ / ฟิลด์ที่ทำให้เกิดข้อผิดพลาด

ในกรณีของฉันนี้เกิดจากการขาดJOINตัวเองซึ่งสร้างข้อผิดพลาดเดียวกันเนื่องจากเขตข้อมูลที่ไม่รู้จัก (ตามที่Andriy ชี้ให้เห็น )


1

แต่คุณสามารถลองเข้าร่วมตารางเช่น

select 
  .... 
from 
   dkcd 
     right join 
                a
                  , b

สิ่งนี้น่าจะใช้ได้


1
SELECT DISTINCT
        phuongxa.maxa ,
        quanhuyen.mahuyen ,
        phuongxa.tenxa ,
        quanhuyen.tenhuyen ,
        ISNULL(dkcd.tong, 0) AS tongdkcd
FROM    phuongxa ,
        quanhuyen
        LEFT OUTER JOIN ( SELECT    khaosat.maxa ,
                                    COUNT(*) AS tong
                          FROM      khaosat
                          WHERE     CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                                              AND
                                                              'Sep 5 2011'
                          GROUP BY  khaosat.maxa
                        ) AS dkcd ON dkcd.maxa = maxa
WHERE   phuongxa.maxa <> '99'
        AND LEFT(phuongxa.maxa, 2) = quanhuyen.mahuyen
ORDER BY maxa;

ใช้ชื่อตารางเองแทนที่จะใช้นามแฝงหากปัญหาการเชื่อมโยงหลายส่วนเกิดขึ้น
SVaidya

1

ข้อผิดพลาดของฉันคือการใช้เขตข้อมูลที่ไม่มีอยู่ในตาราง

table1.field1 => ไม่มีอยู่

table2.field1 => ถูกต้อง

แก้ไขชื่อตารางของคุณ

ข้อผิดพลาดของฉันเกิดขึ้นเนื่องจากการใช้กับ

WITH RCTE AS (
   SELECT...
)
SELECT RCTE.Name, ...
FROM 
  RCTE INNER JOIN Customer
  ON RCTE.CustomerID = Customer.ID 

เมื่อใช้ในการเข้าร่วมกับตารางอื่น ๆ ...


1

คุณลืมที่จะเข้าร่วมตารางบางส่วน? ถ้าไม่เช่นนั้นคุณอาจต้องใช้นามแฝงบางอย่าง


1

ฉันยังดิ้นรนกับข้อผิดพลาดนี้และจบลงด้วยกลยุทธ์เดียวกันกับคำตอบ ฉันรวมคำตอบของฉันเพียงเพื่อยืนยันว่านี่เป็นกลยุทธ์ที่ควรใช้งานได้

นี่คือตัวอย่างที่ฉันทำครั้งแรกหนึ่งเข้าร่วมภายในระหว่างสองตารางฉันรู้ว่าได้รับข้อมูลแล้วสองตัวเชื่อมต่อภายนอกด้านซ้ายบนตารางที่อาจมีแถวที่สอดคล้องกันที่สามารถว่างเปล่า คุณผสมการรวมภายในและการรวมภายนอกเข้าด้วยกันเพื่อให้ได้ผลลัพธ์ด้วย data accross tables แทนที่จะใช้ไวยากรณ์คั่นด้วยเครื่องหมายจุลภาคเริ่มต้นระหว่างตารางและแถวที่พลาดในการเข้าร่วมที่คุณต้องการ

use somedatabase
go 

select o.operationid, o.operatingdate, p.pasid, p.name as patientname, o.operationalunitid, f.name as operasjonsprogram,  o.theaterid as stueid, t.name as stuenavn, o.status as operasjonsstatus from operation o 
inner join patient p on o.operationid = p.operationid 
left outer join freshorganizationalunit f on f.freshorganizationalunitid = o.operationalunitid
left outer join theater t on t.theaterid = o.theaterid
where (p.Name like '%Male[0-9]%' or p.Name like '%KFemale [0-9]%')

ก่อน: ทำการรวมภายในระหว่างตารางที่คุณคาดว่าจะมีการจับคู่ข้อมูล ส่วนที่สอง: ดำเนินการต่อโดยรวมภายนอกเพื่อพยายามดึงข้อมูลในตารางอื่น ๆ แต่จะไม่กรองชุดผลลัพธ์ของคุณหากการรวมตารางภายนอกเข้ากับไม่มีข้อมูลที่ตรงกันหรือตรงกับเงื่อนไขที่คุณตั้งค่าในภาคแสดง / เงื่อนไข


0

ข้อผิดพลาดนี้อาจเกิดจากการขาดเครื่องหมายจุลภาค ,ระหว่างชื่อคอลัมน์ในคำสั่ง SELECT

เช่น:

SELECT MyCol1, MyCol2 MyCol3 FROM SomeTable;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.