SQL - 仅使用INNER JOIN的第一个结果进行选择

时间:2012-12-12 16:17:43

标签: php sql postgresql

我试图从2个表中获得一些结果,它们是1 to n关系。我想从一个表Extensao获得2列,从第二个表HorarioExtensao获得一个结果。我试图按月过滤,但我只想考虑第二列的较低日期,因为相同的结果可能有不同月份的多个日期。

我已经尝试在HorarioExtensao上进行查询,然后使用SELECT执行另一个MIN(h.hora) BETWEEN $inicial and $final,但问题在于我不知道在哪里放INNER JOIN Extensao选择e.nomee.codigo。提前谢谢。

$mes = $_GET["mes"];
$ano = $_GET["ano"];
$inicial = date("Y/m/d g:i:s",mktime(0,0,0,$mes,1,$ano));
$final = date("Y/m/t g:i:s",mktime(0,0,0,$mes,1,$ano));

$db = pg_connect("host=localhost dbname=saga user=**** password=****");
$result = pg_query($db,"SELECT e.nome, MIN(h.hora), e.codigo 
                        FROM Extensao e
                        INNER JOIN HorarioExtensao h ON h.idExtensao = e.idExtensao 
                        WHERE h.hora BETWEEN 
                                to_timestamp('$inicial','YYYY/MM/DD HH:MI:SS') AND
                                to_timestamp('$final','YYYY/MM/DD HH:MI:SS')
                        GROUP BY 3,1");

修改

在桌子上:

- Extensao

 ----------------------
 | ID | NOME | CODIGO |
 |----|------|--------|
 | 1  | N1   | 201    |
 | 2  | N2   | 223    |
 | 3  | N3   | 266    |
 ----------------------

- HorarioExtensao

 ---------------------------
 | idExtensao | hora       |
 |------------|------------|
 | 1          | 2012-01-21 |
 | 1          | 2012-01-22 |
 | 1          | 2012-02-15 |
 | 1          | 2012-02-16 |
 ---------------------------

如果我尝试选择月2,我不希望得到任何结果,因为相同idExtensao的较低日期是第1个月。如果我选​​择月{{1} },我想只得到1个结果,应该是1。另外,我知道N1,2012-01-21,201不是2012-01-21,我只是简化。

2 个答案:

答案 0 :(得分:1)

这个问题留下了解释的余地​​,礼貌地说。

认为这可能就是您要找的内容:预聚合表上的LEFT [OUTER ] JOIN

SELECT e.nome, h.min_hora, e.codigo
FROM   extensao e
LEFT   JOIN (
  SELECT idextensao, min(hora) AS min_hora
  FROM   horarioextensao
  GROUP  BY 1
  ) h ON h.idextensao = e.id
     AND h.min_hora >= to_timestamp($inicial, 'YYYY/MM/DD HH:MI:SS')
     AND h.min_hora <  to_timestamp($final, 'YYYY/MM/DD HH:MI:SS');

在子查询h中,我在加入hora之前从idextensao 中选择最早的horarioextensao extensao

另请注意我如何将WHERE条件提升为LEFT JOIN条件。这样,您就可以获得extensao中的所有行以及horarioextensao中符合条件的所有行。

如果您只想要JOIN中匹配extensao的行,请更改为普通min_hora。在这种情况下,条件可以保留在WHERE子句中。

您示例中的1月结果为:

nome |  min_hora  |  codigo
-----+------------+---------
N1   | 2012-01-21 | 201
N2   | null       | 223
N3   | null       | 266

二月:

nome |  min_hora  |  codigo
-----+------------+---------
N1   | null       | 201
N2   | null       | 223
N3   | null       | 266

->sqlfiddle

答案 1 :(得分:0)

尝试使用此SQL Server语法 - 您需要翻译它,但它应该提供正确的想法

SELECT e.nome,MIN(h.hora),e.codigo 
FROM   Extensao e
       CROSS APPLY 
       (SELECT TOP(1) h.hora
       FROM HorarioExtensao h
       WHERE h.idExtensao = e.idExtensao
             AND
             h.hora >= to_timestamp('$inicial','YYYY/MM/DD HH:MI:SS')
             AND
             h.hora < to_timestamp('$final','YYYY/MM/DD HH:MI:SS')
       ORDER BY h.hora)
GROUP BY 3,1