2

我有如下三张大桌子......

property
--------
property_id
other_prop_data

transfer_property
-----------------
property_id
transfer_id

transfer
--------
transfer_id
contract_date
transfer_price

我想返回在“2012-01-01”和“2012-06-30”之间发生的所有转移的唯一属性 ID 列表。这是我到目前为止的代码......

SELECT *
FROM property p
JOIN
(
  SELECT t.transfer_id, t.contract_date, t.transfer_price::integer, tp.property_id
  FROM transfer t
  LEFT JOIN transfer_property tp ON tp.transfer_id = t.transfer_id
  WHERE t.contract_date BETWEEN '2012-01-01' AND '2012-06-30'
) transfer1 ON transfer1.property_id = p.property_id

AND NOT EXISTS
(
  SELECT transfer2.transfer_id
  FROM
  (
    SELECT t.transfer_id, t.contract_date, t.transfer_price::integer, tp.property_id
    FROM transfer t
    LEFT JOIN transfer_property tp ON tp.transfer_id = t.transfer_id
    WHERE t.contract_date BETWEEN '2012-01-01' AND '2012-06-30'
  ) AS transfer2
  WHERE transfer2.property_id = transfer1.property_id
  AND transfer2.contract_date > transfer1.contract_date
)

这有效(我认为)但非常慢。

我在...中发现了几个类似的查询... https://stackoverflow.com/questions/tagged/greatest-n-per-group ...但我发现的大多数查询都是与同一张表的自连接,而不是连接关系表如上。

我知道在 MySQL 中您可以使用用户变量,但我不知道如何在 PostgreSQL 中执行此操作,或者在这种情况下它是否是理想的解决方案。

有没有人对如何改进这个查询有任何建议(或者甚至如何使用与我上面完全不同的方法来做到这一点)?

很感谢任何形式的帮助。谢谢!

问候,

克里斯

PS:也尝试过 DISTINCT 和 MAX 的变体,但不相信他们会以我使用它们的方式选择最近日期的记录。

编辑:对不起伙计们,我还应该补充一点,我正在 PGADMIN 1.12.3 中运行我的查询

4

3 回答 3

1

尝试ROW_NUMBER() OVER在 PostgreSQL 中使用。这是一个SQLFiddle 示例

SELECT *
FROM property p
JOIN
(
  SELECT t.transfer_id, t.contract_date, 
         t.transfer_price::integer, tp.property_id,
         row_number() over 
           (PARTITION BY tp.property_id 
            ORDER BY t.contract_date desc) as rn
  FROM transfer t
  LEFT JOIN transfer_property tp 
        ON tp.transfer_id = t.transfer_id
  WHERE t.contract_date BETWEEN '2012-01-01' 
                            AND '2012-06-30'
) transfer1 
       ON transfer1.property_id = p.property_id
where transfer1.rn = 1
于 2012-09-12T06:28:34.797 回答
0

Given the skeleton tables:

create table property( property_id serial primary key );

create table transfer(
    transfer_id serial primary key,
    contract_date date not null
);

create table transfer_property (
    property_id integer references property(property_id),
    transfer_id integer references transfer(transfer_id)
);

and data:

insert into property
select nextval('property_property_id_seq') 
from generate_series(1,10);

insert into transfer 
select nextval('transfer_transfer_id_seq'), 
       DATE '2012-01-01' + x * INTERVAL '1 month'
from generate_series(1,10) x;

-- Repeat this 4 or 5 times to produce a pile of duplicate entries
insert into transfer_property (transfer_id,property_id)
select transfer_id, property_id
from property cross join transfer
order by random()
limit 40;

use:

select distinct property_id 
from transfer_property tp inner join transfer t on (tp.transfer_id = t.transfer_id)
where t.contract_date between  '2012-01-01' and '2012-06-30';

Inadequate/misinterpreted? Please post sample data and a real schema that shows the meaningful relationships and expected results.

于 2012-09-12T11:07:08.590 回答
0

“我想返回在 '2012-01-01' 和 '2012-06-30' 之间发生的所有转移的唯一属性 ID 列表。”

对我来说,这表现为:

SELECT DISTINCT tp.property_id
  FROM transfer t
  JOIN transfer_property tp ON tp.transfer_id = t.transfer_id
  WHERE t.contract_date BETWEEN '2012-01-01' AND '2012-06-30'
     ;

现在把它放在一个 CTE 或子查询中,你就完成了:

WITH x1 AS (
      SELECT DISTINCT tp.property_id AS property_id
      FROM transfer t
      JOIN transfer_property tp ON tp.transfer_id = t.transfer_id
      WHERE t.contract_date BETWEEN '2012-01-01' AND '2012-06-30'
      )
SELECT ...
FROM property p
JOIN x1 ON x1.property_id = p.property_id
    ;

我不明白 NOT EXISTS 子查询的目的。你只对MAX感兴趣?

更新:看起来(从标题)你只想要 maxdate。可以通过您不存在的构造或子查询中的此 MAX(...) 来完成;喜欢 ... :

WITH m1 AS (
      SELECT DISTINCT tp.property_id AS property_id
        , MAX(t.contract_date) AS contract_date
      FROM transfer t
      JOIN transfer_property tp ON tp.transfer_id = t.transfer_id
      WHERE t.contract_date BETWEEN '2012-01-01' AND '2012-06-30'
        GROUP BY tp.property_id
      )
SELECT ...
FROM property p
JOIN m1 ON m1.property_id = p.property_id
    ;
于 2012-09-12T11:26:24.947 回答