为什么此多个SQL Server联接查询失败

时间:2019-01-10 15:14:52

标签: sql sql-server join

我有一个这样的表格:

PID   TIV_2011  TIV_2012     LAT         LON
123     1000      1200     20.123489   80.341245
456     1500      3000     21.341287   80.341245
789     2000      1500     21.341287   80.341245
321     1000       750     21.123641   80.238716
567     1500      2300     22.123641   80.238716

问题:对于所有符合以下条件的投保人,编写一个查询以将2012年所有投资总值的总和打印为小数点后2位(TIV_2012):

  1. 具有与一个或多个其他保单持有人相同的TIV_2011值。

  2. 与另一个投保人不在同一个城市(即纬度,经度属性对必须唯一)。

我的查询

select cast(sum(i1.tiv_2012) as decimal(12,2))
from insurance i1 join insurance i2 on i1.tiv_2011 = i2.tiv_2011
where i1.pid != i2.pid 
and i1.lat != i2.lat 
and i1.lon != i2.lon

答案是7250,即1200 + 3000 + 750 + 2300。

但是实际答案应该是4250,即1200 + 750 + 2300

此问题已得到解答,可以正常运行的查询是:

select cast(sum(i1.tiv_2012) as decimal(12,2)) from insurance i1 
join (select TIV_2011 from insurance group by TIV_2011 having count(*) > 1) i2 on i1.tiv_2011 = i2.TIV_2011
join (select lat,LON from insurance group by LAT,LON having COUNT(*) = 1) i3 on i1.LAT = i3.LAT and i1.LON = i3.LON

但是有人可以让我知道我的加入出现问题的原因或原因吗?

4 个答案:

答案 0 :(得分:2)

更喜欢编写反映要求的更直接的SQL。如果要通过连接执行此操作,那么它会很快失去控制,因为连接将相互交叉相乘并增加行数。另外,两个带编号的子句要求使用不同的条件来表达,第二个子句仅对您希望失败的LEFT JOIN起作用。

我希望使用两次EXISTS检查:

declare @t table (PID int, TIV_2011 int, TIV_2012 int, Lat decimal(8,6),Lon decimal(9,6))
insert into @t(PID,TIV_2011,TIV_2012,LAT,LON) values
(123,1000,1200,20.123489,80.341245),
(456,1500,3000,21.341287,80.341245),
(789,2000,1500,21.341287,80.341245),
(321,1000, 750,21.123641,80.238716),
(567,1500,2300,22.123641,80.238716)

select
    CONVERT(decimal(12,2),SUM(TIV_2012))
from
    @t t_keep
where
    exists (select * from @t t_other2011
       where t_keep.PID != t_other2011.PID
       and t_keep.TIV_2011 = t_other2011.TIV_2011
) and
    not exists (select * from @t t_city
       where t_keep.PID != t_city.PID and
       t_keep.Lat = t_city.Lat and
       t_keep.Lon = t_city.Lon)

@tt_keep)中选择行,其中(第一个EXISTS)中表中的另一行针对另一个保单持有人,我们共享相同的TIV_2011值。但也(and,其中(第二EXISTS)在表中的另一位保单持有人的行中不是 ,我们共享相同的Lat和{{ 1}}值。

这将产生4250的值。

答案 1 :(得分:1)

您有两个独立的条件,但是尝试一起使用。例如,使用子查询将它们拆分出来,您将获得预期的结果。

DECLARE @Test TABLE (
    PID         int,
    TIV_2011    int,
    TIV_2012    int,
    LAT         DECIMAL(8,6),        
    LON         DECIMAL(8,6)
) 
INSERT @Test(PID,   TIV_2011,  TIV_2012,     LAT,         LON)
VALUES
(123, 1000, 1200, 20.123489, 80.341245),
(456, 1500, 3000, 21.341287, 80.341245),
(789, 2000, 1500, 21.341287, 80.341245),
(321, 1000,  750, 21.123641, 80.238716),
(567, 1500, 2300, 22.123641, 80.238716)

select cast(sum(i1.tiv_2012) as decimal(12,2))
from @Test i1 
    join @Test i2 on i1.tiv_2011 = i2.tiv_2011
        AND i1.pid != i2.pid 
where 
    NOT EXISTS (
        SELECT 1
        FROM @Test
        WHERE LAT = i1.lat 
            and LON = i1.lon
            AND PID != i1.pid
    )

答案 2 :(得分:1)

这根本不是我要参加的任务。

Private Sub CommandButton1_Click()

Dim emptyRow As Long

'Validation
If WorksheetFunction.CountIf(Sheets("RawData").Range("A:A"), 
Me.TextBox1.Value) = False Then
    MsgBox "Ticket Does Not Exist", vbCritical
End If

'Determine emptyRow
emptyRow = WorksheetFunction.CountA(Range("A:A")) + 1

'Transfer information
With ThisWorkbook.Sheets("WOTracker")
    .Cells(2, 1).EntireRow.Insert
    .Cells(2, 1).Value = TextBox1.Value
    .Cells(2, 5).Value = TextBox2.Value
    .Cells(2, 2).Value = TextBox3.Value
    .Cells(2, 3).Value = TextBox4.Value
    .Cells(2, 6).Value = TextBox5.Value
    .Cells(2, 7).Value = ComboBox1.Value
    .Cells(2, 8).Value = ComboBox2.Value
    .Cells(2, 9).Value = TextBox8.Value
    .Cells(2, 4).Value = TextBox9.Value
    End With

'Formatting
Dim dDate As Date
dDate = DateSerial(Month(Date), Day(Date), Year(Date))
TextBox2.Value = Format(TextBox2.Value, "mm/dd/yy")
dDate = TextBox2.Value

With ThisWorkbook.Sheets("WOTracker")
    Sheets("WOTracker").Range("A2:Z2").Font.Bold = False
    Sheets("WOTracker").Range("A2:Z2").Font.Underline = xlUnderlineStyleNone
    End With
End Sub

我知道这不能回答您的问题,您的联接到底有什么问题。在我看来,这是只在表中查找其他行时甚至在这里使用联接的方法。对于查找记录,我们有select sum(tiv_2012) from insurance i where exists ( select * from mytable other where other.pid <> i.pid and other.tiv_2011 = i.tiv_2011 ) and not exists ( select * from mytable other where other.pid <> i.pid and other.lat = i.lat and other.lon = i.lon ); EXISTS,并且条件根据需要进入IN子句。

答案 3 :(得分:0)

您的这一行是不同的,没有道理。

i1.pid != i2.pid 

那不需要在那里。