仅从多个表中选择相同的列,其中某些内容=某些内容

Ada*_*own 8 sql

我有两个结构非常相似的表.

Universidades
nombre | contenido | becas | fotos etc etc etc
Internados
nombre | todo | becas | fotos etc etc etc
Run Code Online (Sandbox Code Playgroud)

我想写一个SQL语句,它将nombre从它们中选择它们并仅在匹配时将其作为数组返回.从我所看到的UNION SELECT似乎是这样做的方式.我WHERE在最后添加了,我认为这是它出错的地方.到目前为止,我收到了第一张表的第一行.

我打错了什么?

$db = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD);
$data = $db->prepare("SELECT nombre FROM internados UNION SELECT nombre FROM universidades WHERE nombre = ?");
$data->execute(array($nombre));
Run Code Online (Sandbox Code Playgroud)

道歉,我想从这两个表中检索一个结果.在Namees nombre列都是独立的两个表中的不同

Eri*_*ikE 20

One issue to point out before we solve the problem is that each query in a UNION is distinct and requires its own WHERE clause. The only clause that applies to the UNION as a whole is ORDER BY. So your query as is needs some tweaking:

SELECT nombre
FROM dbo.internados
WHERE nombre = ? -- the added line
UNION
SELECT nombre
FROM dbo.universidades
WHERE nombre = ?
;
Run Code Online (Sandbox Code Playgroud)

Second, if you want the two tables to both have the same nombre (which is not completely clear but I'm guessing that's right), then that won't work because it simply returns one nombre if the value is found in either table. Probably the best way to solve this is to just do a join:

SELECT I.nombre
FROM
   dbo.internados I
   INNER JOIN dbo.universidades U
      ON I.nombre = U.nombre
WHERE
   I.nombre = ?
   AND U.nombre = ? -- perhaps not needed, but perhaps helpful
;
Run Code Online (Sandbox Code Playgroud)

I am not 100% sure that I understand exactly what you're looking for, so please speak up if I've missed the mark.

You can think about JOIN and UNION this way:

  • JOIN: connects rows horizontally
    • Matches them on conditions
    • Creates new columns
    • Doesn't exactly create rows because all data comes from existing rows, but it will duplicate a row from one input when the conditions match multiple rows in the other input. If both inputs have duplicates then it multiplies the count of rows from one input by the count of matching rows from the other.
    • If there is no match condition at all (think CROSS JOIN) then you can get a cartesian product which is each row in one input matched to each row in the other.
    • When using an OUTER join--LEFT, RIGHT, FULL--if rows from the inner input (or either input with FULL) do not match the other, NULLs will be placed into the columns for the other input.
  • UNION: stacks rows vertically
    • Generally, creates new rows
    • 没有使用任何条件,没有真正的匹配
    • UNIONUNION ALL单独(不)将删除重复的行,即使一个输入没有行

请注意,UNION可以对其进行修改以完成工作,但这并不理想:

SELECT nombre
FROM (
   SELECT nombre
   FROM dbo.internados
   WHERE nombre = ?
   UNION ALL
   SELECT nombre
   FROM dbo.universidades
   WHERE nombre = ?
) N
GROUP BY nombre
HAVING Count(*) = 2
;
Run Code Online (Sandbox Code Playgroud)

通过这种方式,我们确保有两个值.请注意,这假设每个表中不能有两个相同的名称.如果这是真的,那么需要做更多的工作才能使UNION方法完成工作.

  • 谢谢,这是对JOIN和UNION的一个很好的解释.我想我一开始就误解了他们,我需要对其进行重组. (4认同)
  • 我添加了一些关于`JOIN`和`UNION`的更多细节. (4认同)

zmo*_*zmo 5

大部分时间union都可以通过加入来实现:

SELECT nombre 
  FROM internados 
UNION 
SELECT nombre 
  FROM universidades 
 WHERE nombre = ?
Run Code Online (Sandbox Code Playgroud)

最好是:

SELECT nombre
  FROM internados i
  JOIN universidades u
    ON i.nombre = u.nombre
   AND nombre = ?
Run Code Online (Sandbox Code Playgroud)

这更容易阅读.(您也可以使用JOIN语法,但我更喜欢普通的旧手动连接).

但无论这是a union还是a join,都要记住两个表都在结果中合并:

nombre | todo | becas | fotos | ... | contenido | becas | ...
Run Code Online (Sandbox Code Playgroud)

所以基本上,当你在nombre上放一个条件时,你要么得到一个空集,要么给你给查询的名字.但是,按照你编写联盟的方式,只有第二组才能where应用条件,而不是第一组.你应该把条件放在工会的两个查询上:

SELECT nombre 
  FROM internados 
 WHERE nombre = ?
UNION 
SELECT nombre 
  FROM universidades 
 WHERE nombre = ?
Run Code Online (Sandbox Code Playgroud)

  • 旧式非ANSI连接?在2013年!?!?世界到底是什么?我不能推荐这个. (3认同)
  • 好的,好的,解决这个问题,你是对的,是时候进入SQL的XXIst世纪了;-) (3认同)
  • 我是戏剧性的,但感谢你的倾听.:) (3认同)