这个查询结果有意义吗?

时间:2016-03-11 02:47:34

标签: sql-server inner-join exists

最初,我有一个名为acc_account的表,其中列出了公司或组织使用的所有帐户。假设我在这个表中有518行:

500行是使用的帐户,另外18行描述不同类型的帐户。它用于在会计应用程序中创建报告。我不知道为什么他们将2个不同的部分包含在一个表中,但它是这样创建的。

无论如何,这个存储过程名为acc_qry_chart_of_accounts,基本上它列出了组织/公司使用的所有帐户。

在存储过程本身内部学习时,我发现了一些理解查询的问题,这是我在下面展示的内容。

基本上,因为有18行包含在一起,所以18行中的一些不得显示在结果中,例如:我们没有任何账户类型的'EI'(特殊收入)。我必须从结果中排除它。

下面的查询是他们用来排除这些帐户的示例,我个人不明白为什么父列(aka parent_code)可以与acc_code相同,为什么它必须使用不同的别名?

所以,我决定问这个关于查询本身的问题,这就是为什么我在这里。

我内部使用不同的别名加入一个表。 然后,我使用此查询创建一个查询WHERE EXISTS'parent'列等于'acc_code'列:

SELECT * FROM acc_account 
INNER JOIN acc_account a2 ON acc_account.acc_code=a2.acc_code 
WHERE EXISTS (SELECT * FROM acc_account WHERE acc_account.parent=a2.acc_code);

结果如下:

acc_id   acc_code            parent           name
-------  ------------------ ---------  ---------------------------
2       |  CA              |  -1     |   CURRENT ASSETS 
3       |  CL              |  -1     |   CURRENT LIABILITIES
4       |  CP              |  -1     |   CAPITAL/RETAINED EARNINGS
5       |  CS              |  -1     |   COST OF GOODS SALES
7       |  EX              |  -1     |   EXPENSES

您可以看到父数据和acc_code数据首先不相等,但它产生了上面的输出。

现在,当我使用相同的查询但将acc_account.parent=a2.acc_code之前的最后一行更改为acc_account.parent=acc_account.acc_code时:

SELECT * FROM acc_account 
    INNER JOIN acc_account a2 ON acc_account.acc_code=a2.acc_code 
    WHERE EXISTS (SELECT * FROM acc_account WHERE acc_account.parent=acc_account.acc_code);

结果:

acc_id   acc_code            parent           name
 -------  ------------------ ---------  ---------------------------
        |                   |         |                              

没有应有的结果。那么为什么首先如果我尝试使用不同的别名,它会产生不同的结果呢?

以下查询返回0行:

select * from acc_account where parent=acc_code;

我的问题,a1& a2是同一张桌子还是我弄错了?

条件a1.parent=a2.acc_codea1.parent=a1.acc_code相同,在这种情况下,两个表相同且包含相同的数据?

2 个答案:

答案 0 :(得分:1)

您正在编写的查询基本上是这样的:

SELECT a.*
FROM acc_account a INNER JOIN
     acc_account a2
     ON a.acc_code = a2.acc_code 
WHERE EXISTS (SELECT 1 FROM acc_account a3 WHERE a3.parent = a2.acc_code);

三个acc_account的单独引用。子查询中引用的parent与输出的父项无关。

您修改的查询只是删除了相关原因而没有匹配的行,因此不会返回任何内容。

答案 1 :(得分:0)

您的第一个查询:

SELECT * 
FROM acc_account 
INNER JOIN acc_account a2 
    ON acc_account.acc_code = a2.acc_code 
WHERE EXISTS (
    SELECT * 
    FROM acc_account 
    WHERE acc_account.parent = a2.acc_code
);

搜索父acc_account。由于您在SELF JOIN子句中使用了相同的列,因此ON非常重要。没有它,SELF JOIN的结果将是相同的。然后,WHERE子句使用以下条件检查父acc_account

WHERE acc_account.parent = a2.acc_code

您的第二个问题:

SELECT * 
FROM acc_account 
INNER JOIN acc_account a2 
    ON acc_account.acc_code = a2.acc_code 
WHERE EXISTS (
    SELECT * 
    FROM acc_account 
    WHERE 
        acc_account.parent = acc_account.acc_code
);
除了WHERE子句之外,

与第一个相同。这里:

SELECT * 
FROM acc_account 
WHERE 
    acc_account.parent = acc_account.acc_code

由于没有acc_count是其自身的父级,因此它不返回任何行,导致EXISTS条件为FALSE,并且查询不返回任何行。 / p>

请注意,由于acc_account被多次引用,其中两个没有别名,因此子查询中的条件为:

acc_account.parent = acc_account.acc_code

引用子查询中的表,最近的一个表示比较同一行但不同的列。

你想要的是:

SELECT * 
FROM acc_account a1
WHERE EXISTS (
    SELECT * 
    FROM acc_account a2
    WHERE 
        a2.parent = a1.acc_code
);

这就是别名的重要性所在。