复杂的SQL语句需要改进

时间:2019-10-05 16:03:20

标签: sql sql-server

在另一个线程上问了一个问题,为什么我的复杂SQL语句不起作用(通常会收到奇怪的“元组”消息)后,让我印象深刻的是,我的SQL语法很糟糕。我很容易接受这一点,因为我对复杂的SQL知识还比较陌生,所以我希望那些比我了解得更多的人(我猜大多数人)可以为我提供帮助。

这是需要的全部内容:
这是来自一个物业管理系统,该系统没有(上帝帮我)有身份列,而是依靠“ dept_no”(属性)和“ unit”的组合。在一个表中包含“ rent_amoun”列(奇怪的字段名称,因为以前是从Visual FoxPro扩展而来的,该字段仅允许10个字符字段名称)。

然后有一个“ trans”表(事务),其中包含每个属性和单位中每个人进行的每种事务类型。从该表中,我需要找到每个dept_no / unit组合的“到期租金”记录(按降序排列),并找到比第一个表中的租金少的第一条记录。

然后,我必须从trans表中获取“ amt_charge”和“ transcti2”(transaction_date)的内容,并将这些值插入第三张表(rentinc)的“ oldrent”和“ idate”列中。 因此,我意识到下面的SQL语句是业余的,但实际上可以在SSMS的“查询”窗口中使用,但是给我带来了odbc_connect()的许多问题(连接字符串中没有“ SQL_CUR_USE_ODBC”的“ tuples”错误和带有“ Ambiguous amt_charge”的错误)它)。

这是电话:

SELECT x.dept_no,
       x.unit,
       x.amt_charge,
       q.rent_amoun,
       CONVERT(DATE, x.transacti2, 101) AS transacti2 
FROM (SELECT TOP (100) PERCENT
             t.dept_no,
             t.unit,
             t.amt_charge,
             l.rent_amoun 
      FROM (SELECT TOP (100) PERCENT
                   w.dept_no,
                   w.unit,
                   w.amt_charge 
            FROM trans w 
            WHERE (transacti3 = 'Rent Due') 
            GROUP BY w.dept_no,
                     w.unit,
                     w.amt_charge 
            ORDER BY w.dept_no,
                     w.unit,
                     w.amt_charge
           ) AS t 
           INNER JOIN lease_unit AS l ON t.dept_no = l.dept_no
                                AND t.unit = l.unit 
      ORDER BY t.dept_no,
               t.unit,
               t.amt_charge DESC
      ) AS q 
      INNER JOIN trans AS x ON x.dept_no = q.dept_no
                           AND x.unit = q.unit 
WHERE x.amt_charge IS NOT NULL
  AND x.transacti3 = 'Rent Due'
ORDER BY x.dept_no,
         x.unit,
         x.transacti2 DESC;

1 个答案:

答案 0 :(得分:0)

这不是答案,而是注释部分中不适合的注释。

当子查询中包含子查询时,我建议您使用CTE(公用表表达式)重新表述整个查询。例如,您的查询如下所示:

WITH
t as (
  SELECT TOP (100) PERCENT
    w.dept_no, 
    w.unit, 
    w.amt_charge 
  FROM trans w 
  WHERE (transacti3 = 'Rent Due') 
  GROUP BY w.dept_no, w.unit, w.amt_charge 
  ORDER BY w.dept_no, w.unit, w.amt_charge
),
q as (
  SELECT TOP (100) PERCENT
    t.dept_no,
    t.unit,
    t.amt_charge,
    l.rent_amoun 
  FROM t 
  INNER JOIN lease_unit AS l ON t.dept_no = l.dept_no AND t.unit = l.unit 
  ORDER BY t.dept_no, t.unit, t.amt_charge DESC
)
SELECT x.dept_no,
       x.unit,
       x.amt_charge,
       q.rent_amoun,
       CONVERT(DATE, x.transacti2, 101) AS transacti2 
FROM q 
INNER JOIN trans AS x ON x.dept_no = q.dept_no AND x.unit = q.unit 
WHERE x.amt_charge IS NOT NULL
  AND x.transacti3 = 'Rent Due'
ORDER BY x.dept_no, x.unit, x.transacti2 DESC

这样,您可以先测试子查询以检查它们是否在做正确的事情。例如,要检查q

WITH
t as (
  SELECT TOP (100) PERCENT
    w.dept_no, 
    w.unit, 
    w.amt_charge 
  FROM trans w 
  WHERE (transacti3 = 'Rent Due') 
  GROUP BY w.dept_no, w.unit, w.amt_charge 
  ORDER BY w.dept_no, w.unit, w.amt_charge
),
q as (
  SELECT TOP (100) PERCENT
    t.dept_no,
    t.unit,
    t.amt_charge,
    l.rent_amoun 
  FROM t 
  INNER JOIN lease_unit AS l ON t.dept_no = l.dept_no AND t.unit = l.unit 
  ORDER BY t.dept_no, t.unit, t.amt_charge DESC
)
select * from q -- this line queries q. Or you can check t here...

使用最后一个SELECT,检查每个部分的操作是否正确。然后,您可以测试整个过程。

相关问题