如何在MySQL中从表1中检索表2中没有相关行的行

如何在MySQL中从表1中检索表2中没有相关行的行,mysql,join,Mysql,Join,我有一个有趣的问题——我需要JOIN语句的完全相反的形式 我有一个叫做发票的表格,还有一个叫做付款的表格。我想按顺序检索没有附加任何付款的发票,但后面是附加了付款的行 发票表包含以下字段: 身份证件 客户ID 时间戳 付款表包含以下字段: 身份证件 发票ID 数量 并非所有付款都是全额付款,因此每张发票可能附带多笔付款 我希望未付款的发票先是没有付款的发票,然后是部分付款但没有全额付款的发票,然后是全额付款的发票 如果可以的话,我希望在不必运行单独的SQL查询的情况下执行此操作-我希望它是一个查

我有一个有趣的问题——我需要JOIN语句的完全相反的形式

我有一个叫做发票的表格,还有一个叫做付款的表格。我想按顺序检索没有附加任何付款的发票,但后面是附加了付款的行

发票表包含以下字段:

身份证件 客户ID 时间戳 付款表包含以下字段:

身份证件 发票ID 数量 并非所有付款都是全额付款,因此每张发票可能附带多笔付款

我希望未付款的发票先是没有付款的发票,然后是部分付款但没有全额付款的发票,然后是全额付款的发票

如果可以的话,我希望在不必运行单独的SQL查询的情况下执行此操作-我希望它是一个查询,这样我就可以吐出一次。有什么想法吗

-更新-

根据DCP的回答,我更新了查询方法。我一直在工作,直到我需要将JOIN语句添加到order by我的sub_to_inv表,如下所示:

id订阅发票 0 12 18 1 13 18 21419

等等

因此,基于此,我提出了一个建议,在末尾增加了限制,即逐页限制

SELECT i.id AS id, i.modify_date as modify_date, s.subscription as subscriptionid, 0 paidratio FROM invoices i
LEFT JOIN sub_to_inv s ON i.id=s.invoice
WHERE NOT EXISTS (SELECT id FROM payments p WHERE p.invoice=i.id) AND i.corporation='3' AND i.payer=1

UNION ALL
SELECT i.id AS id, i.modify_date as modify_date, s.subscription as subscriptionid, p.paid/i.total AS paidratio FROM invoices i,
(SELECT p.invoice, sum(amount) AS paid FROM payments p GROUP BY p.invoice) p
LEFT JOIN sub_to_inv s ON i.id=s.invoice
WHERE p.invoice=i.id AND i.corporation='3' AND i.payer=1

AND p.paid UNION ALL
SELECT i.id AS id, i.modify_date as modify_date, s.subscription as subscriptionid, p.paid/i.total AS paitratio FROM invoices i,
(SELECT p.invoice, sum(amount) AS paid FROM payments p WHERE p.invoice=id GROUP BY p.invoice) p
LEFT JOIN sub_to_inv s ON i.id=s.invoice
WHERE p.invoice = i.id AND i.corporation='3' AND i.payer=1

AND p.paid=i.total

ORDER BY paidratio DESC, modify_date DESC, subscriptionid ASC LIMIT 0,40

我得到了一个我没有得到的I.id列未找到错误。在最终通过UNION语句组合的每个语句块上,我指定发票I以确保I.id引用发票的id。tab.e

如果我假设您有一个包含总金额的发票明细表:

其中paidstatus:

1=未付 2=部分支付
3=已付款

如果我假设您有一个发票明细表,其中包含总金额:

其中paidstatus:

1=未付 2=部分支付
3=已付

从不存在的表1中选择*,从表2中选择*,其中表2.foreignkey=表1.primarykey


这行吗?

从不存在的表1中选择*,从表2中选择*,其中表2.foreignkey=表1.primarykey


这行得通吗?

从你的问题来看,我看不出任何方法来判断发票是否已全额付款,但下面将为你提供一个没有付款的发票列表,然后是一个有付款的发票列表

select *
from
 invoices
where
 not exists (
  select 1
  from payments
  where invoices.id = payments.invoiceid
 )

union

select *
from
 invoices
where
 exists (
  select 1
  from payments
  where invoices.id = payments.invoiceid
 )

从你的问题来看,我看不出任何方法来判断发票是否已全额付款,但下面将为你提供一个没有付款的发票列表,然后是一个有付款的发票列表

select *
from
 invoices
where
 not exists (
  select 1
  from payments
  where invoices.id = payments.invoiceid
 )

union

select *
from
 invoices
where
 exists (
  select 1
  from payments
  where invoices.id = payments.invoiceid
 )

您没有告诉我们如何确定发票总额,但我假设您的发票表中有一些字段用于此目的。在下面的例子中,我假设它被称为TOT_AMT

这种方法背后的思想是,我们通过三个单独的步骤获取数据,并使用UNION ALL将三个部分粘合在一起。我们使用一个名为PAY_TYPE的伪列来获取您想要的订单,即先是没有付款的发票,然后是部分付款的发票,最后是全额付款的发票

下面显示了一个完整的工作示例,我使用了Oracle,但我认为您可以轻松地将其应用于MySQL

CREATE TABLE invoices (ID number, tot_amt NUMBER);
CREATE TABLE payments (ID NUMBER, invoice_id NUMBER, amount NUMBER);

INSERT INTO invoices VALUES (1,100);
INSERT INTO invoices VALUES (2,200);
INSERT INTO invoices VALUES (3,300);

INSERT INTO payments VALUES (1,1,20);
INSERT INTO payments VALUES (2,1,40);

INSERT INTO payments VALUES (3,3,150);
INSERT INTO payments VALUES (4,3,120);
INSERT INTO payments VALUES (5,3,30);

/* get invoices with no payments */
SELECT i.id
     , i.TOT_AMT
     , 0               TOT_PAID
     , '0_NO_PAYMENTS' PAY_TYPE
  FROM invoices i
  WHERE NOT EXISTS (SELECT * FROM PAYMENTS P WHERE P.INVOICE_ID = I.ID)
UNION ALL
/* get invoices with partial payments */
SELECT i.id
     , i.TOT_AMT
     , p.tot_paid
     , '1_PARTIALLY_PAID' PAY_TYPE
  FROM invoices i
     , (SELECT P.INVOICE_ID
             , SUM(AMOUNT) tot_paid
          FROM PAYMENTS P
         GROUP BY P.INVOICE_ID) p
 WHERE P.INVOICE_ID = I.ID
   AND p.TOT_PAID < i.TOT_AMT
UNION ALL
/* get invoices that are fully paid */
SELECT i.id
     , i.TOT_AMT
     , p.tot_paid
     , '2_FULLY_PAID' PAY_TYPE
  FROM invoices i
     , (SELECT P.INVOICE_ID
             , SUM(AMOUNT) tot_paid
          FROM PAYMENTS P
         GROUP BY P.INVOICE_ID) p
 WHERE P.INVOICE_ID = I.ID
   AND p.TOT_PAID = i.TOT_AMT
ORDER BY PAY_TYPE   

您没有告诉我们如何确定发票总额,但我假设您的发票表中有一些字段用于此目的。在下面的例子中,我假设它被称为TOT_AMT

这种方法背后的思想是,我们通过三个单独的步骤获取数据,并使用UNION ALL将三个部分粘合在一起。我们使用一个名为PAY_TYPE的伪列来获取您想要的订单,即先是没有付款的发票,然后是部分付款的发票,最后是全额付款的发票

下面显示了一个完整的工作示例,我使用了Oracle,但我认为您可以轻松地将其应用于MySQL

CREATE TABLE invoices (ID number, tot_amt NUMBER);
CREATE TABLE payments (ID NUMBER, invoice_id NUMBER, amount NUMBER);

INSERT INTO invoices VALUES (1,100);
INSERT INTO invoices VALUES (2,200);
INSERT INTO invoices VALUES (3,300);

INSERT INTO payments VALUES (1,1,20);
INSERT INTO payments VALUES (2,1,40);

INSERT INTO payments VALUES (3,3,150);
INSERT INTO payments VALUES (4,3,120);
INSERT INTO payments VALUES (5,3,30);

/* get invoices with no payments */
SELECT i.id
     , i.TOT_AMT
     , 0               TOT_PAID
     , '0_NO_PAYMENTS' PAY_TYPE
  FROM invoices i
  WHERE NOT EXISTS (SELECT * FROM PAYMENTS P WHERE P.INVOICE_ID = I.ID)
UNION ALL
/* get invoices with partial payments */
SELECT i.id
     , i.TOT_AMT
     , p.tot_paid
     , '1_PARTIALLY_PAID' PAY_TYPE
  FROM invoices i
     , (SELECT P.INVOICE_ID
             , SUM(AMOUNT) tot_paid
          FROM PAYMENTS P
         GROUP BY P.INVOICE_ID) p
 WHERE P.INVOICE_ID = I.ID
   AND p.TOT_PAID < i.TOT_AMT
UNION ALL
/* get invoices that are fully paid */
SELECT i.id
     , i.TOT_AMT
     , p.tot_paid
     , '2_FULLY_PAID' PAY_TYPE
  FROM invoices i
     , (SELECT P.INVOICE_ID
             , SUM(AMOUNT) tot_paid
          FROM PAYMENTS P
         GROUP BY P.INVOICE_ID) p
 WHERE P.INVOICE_ID = I.ID
   AND p.TOT_PAID = i.TOT_AMT
ORDER BY PAY_TYPE   
如果这行得通,我会惊讶的

select sub.*, paid/tot_amt as ordering_column
from (
 select
    i.id,
    i.customerid,
    i.timestamp,
    i.tot_amt,
    (select sum(ifnull(p.amount,0)) from payments p where p.invoiceid = i.id ) as paid
 from invoices i
) sub
order by ordering_column
如果这行得通,我会惊讶的

select sub.*, paid/tot_amt as ordering_column
from (
 select
    i.id,
    i.customerid,
    i.timestamp,
    i.tot_amt,
    (select sum(ifnull(p.amount,0)) from payments p where p.invoiceid = i.id ) as paid
 from invoices i
) sub
order by ordering_column
这将为您提供按所需方式排序的发票,以及每张发票的支付金额总和


这将为您提供按所需方式排序的发票,以及每张发票的已付款金额之和

我如何知道发票是否已部分付款?发票金额还链接到另一个表,该表包含购买的详细信息。。相当复杂。但是,如果我了解排序无附件行和有附件行的基本机制,我就可以解决这个问题。我如何知道发票是否已部分支付?发票金额还链接到另一个包含所购买内容详细信息的表。。相当复杂。但是,如果我理解了排序无附件行和有附件行的基本机制,我就可以解决这个问题;检查所有where条件后,将添加空行。如果进行了多次付款,这将返回多行,他只需要订购发票。我已尝试构建

仔细检查SQL并得到一个语法错误:选择i.id作为id,当从付款中选择SUMamount时为CASE,其中p.invoice=i.id按p.invoice=i.total分组,然后当从付款中选择SUMamount时为3,其中p.invoice=i.id按p.invoice