Mysql 如何在子查询中绕过对外部表的引用?

Mysql 如何在子查询中绕过对外部表的引用?,mysql,subquery,aggregate-functions,Mysql,Subquery,Aggregate Functions,我一直在处理这两张表: 文件 版本 有一个页面,我想列出所有文档及其属性。 我想从每个文档中添加一个单独的have status。 状态可以从相应版本的最新日期派生。 可能正在接受旧版本 我要查找的查询结果如下: id company_id etc status ================================== 1 2 x accepted 2 2 x created 我首先做了

我一直在处理这两张表:

文件

版本

有一个页面,我想列出所有文档及其属性。 我想从每个文档中添加一个单独的have status。 状态可以从相应版本的最新日期派生。 可能正在接受旧版本

我要查找的查询结果如下:

id    company_id    etc   status
==================================
1     2             x     accepted
2     2             x     created
我首先做了一个查询,将所有日期合并在一起,并在旁边添加一个状态。 它按预期工作,当我添加文档id时,一切看起来都正常

SELECT `status`
FROM (
    SELECT max(date_created) as `date`,'created' as `status` FROM version WHERE document_id = 1
    UNION
    SELECT max(date_issued),'issued' FROM version WHERE document_id = 1
    UNION
    SELECT max(date_accepted),'accepted' FROM version WHERE document_id = 1
    ORDER BY date DESC
    LIMIT 1
) as maxi
当我试图将此查询合并为子查询时,我无法使其工作

SELECT *, (
  SELECT `status` FROM (
    SELECT max(date_created) as `date`,'created' as `status`FROM version WHERE document_id = document.id
    UNION
    SELECT max(date_issued),'issued' FROM version WHERE document_id = document.id
    UNION
    SELECT max(date_accepted),'accepted' FROM version WHERE document_id = document.id
    ORDER BY date DESC
    LIMIT 1
  ) as maxi
) as `status`
FROM `document`
这将在“where子句”中获取错误未知列“document.id”。所以我在So上读了很多书,认为它根本无法达到value offer.id,因为它是子查询中的一个子查询。因此,我尝试采用另一种方法,一次获取所有状态,以避免WHERE语句,并加入它们。我最后提出了下一个问题

SELECT MAX(`date`),`status`, document_id
FROM (
    SELECT datetime_created as `date`, 'created' as `status`,document_id FROM `version`
    UNION
    SELECT datetime_issued, 'issued',document_id FROM `version`
    UNION
    SELECT datetime_accepted, 'accepted',document_id FROM `version`
) as dates
GROUP BY offer_id

这次没有错误,但我意识到状态不可能是正确的,因为它在分组过程中丢失了。我尝试了两者的结合,但这两个缺点一直阻碍着我。有谁能建议如何在不更改数据库的情况下在单个查询中执行此操作?我知道将日期保存在一个单独的表中只是简单的事情

我没有测试过这个,但是你可以这样做,你可能需要调整细节

它基本上是从一个完全不同的角度来看待它

 select
    d.*,
    (CASE GREATEST(ifnull(v.date_created, 0), ifnull(v.date_issued,0), ifnull(v.date_accepted,0) ) 
      WHEN null THEN 'unknown'
      WHEN v.date_accepted THEN 'accepted'
      WHEN v.date_issued THEN 'issued'
      WHEN v.date_created THEN 'created'
      END) as status 
from document d
left join version v on 
    v.document_id = d.document_id and 
    not exists (select 1 from (select * from version) x where x.document_id = v.document_id and x.id <> v.id and x.version > v.version)

您能否将表格设计正常化,以便将状态/日期从版本移动到不同的表格上

如果没有,可能是这样的:-

SELECT Document.id, Document.company_id, Document.etc, CASE WHEN Sub1.status = 3 THEN 'accepted' WHEN Sub1.status = 2 THEN 'issued' WHEN Sub1.status = 1 THEN 'created' ELSE NULL END AS status
FROM Document
INNER JOIN (
    SELECT document_id, MAX(CASE WHEN date_accepted IS NOT NULL THEN 3 WHEN date_issued IS NOT NULL THEN 2 WHEN date_created IS NOT NULL THEN 1 ELSE NULL END) AS status 
    FROM Version
    GROUP BY document_id
) Sub1
ON Document.id = Sub1.document_id

子选择从版本表中获取任何文档的最高状态。每个可能版本的最高状态都以数字的形式返回,通过在文档id上分组,它将获得任何版本的最高状态。这将与文档表和转换为文本描述的版本号的编号连接起来。

最大值选择最大值。我并不认为日期总是有顺序的。如果它们总是按顺序排列,您只需进行一些检查,看看它是否为NULL。如果任何参数为NULL,则根据最大返回NULL。在所有情况下,当没有一个可接受的版本document@tomas,完全正确,我更改了它。在我看来,“不存在”条件试图从两个条件中获取最新版本。但是可能会有更多的版本,并且可能会接受以前的版本。非extsts将始终采用最新版本。它检查是否有版本号更高的版本记录。因此,它将始终使用最新版本记录您的起点,最新版本,不适用于我的情况。任何版本都可以接受。验收将是最终事件。好的。让我想想,我能帮你什么忙。
 select
    d.*,
    (CASE GREATEST(ifnull(v.date_created, 0), ifnull(v.date_issued,0), ifnull(v.date_accepted,0) ) 
      WHEN null THEN 'unknown'
      WHEN v.date_accepted THEN 'accepted'
      WHEN v.date_issued THEN 'issued'
      WHEN v.date_created THEN 'created'
      END) as status 
from document d
left join version v on 
    v.document_id = d.document_id and 
    not exists (select 1 from (select * from version) x where x.document_id = v.document_id and x.id <> v.id and x.version > v.version)
select Doc.document_id,Doc.company_id,Doc.etc,f.status
from Document Doc
inner join 
    (select Ver.document_id,
    case when Ver.date_accepted is not null then 'Accepted'
    when Ver.date_issued is not null then 'Issued'
    when Ver.date_created is not null then 'Created'
    end as status
from version Ver
inner join (
                select document_id,MAX(version) VersionId
                from version
                group by document_id
            )t on t.document_id=Ver.document_id 
where t.VersionId=Ver.version
)f on Doc.document_id=f.document_id
SELECT Document.id, Document.company_id, Document.etc, CASE WHEN Sub1.status = 3 THEN 'accepted' WHEN Sub1.status = 2 THEN 'issued' WHEN Sub1.status = 1 THEN 'created' ELSE NULL END AS status
FROM Document
INNER JOIN (
    SELECT document_id, MAX(CASE WHEN date_accepted IS NOT NULL THEN 3 WHEN date_issued IS NOT NULL THEN 2 WHEN date_created IS NOT NULL THEN 1 ELSE NULL END) AS status 
    FROM Version
    GROUP BY document_id
) Sub1
ON Document.id = Sub1.document_id