单个查询从具有不同列的多个表中获取记录

Posted

技术标签:

【中文标题】单个查询从具有不同列的多个表中获取记录【英文标题】:Single Query to fetch records from multiple tables with different columns 【发布时间】:2017-07-12 07:24:04 【问题描述】:

我有 2 个不同的表想要在单个查询中获取记录。目前,我正在使用 2 个查询,然后合并数组结果,然后显示记录。以下是我当前的代码:

$db = JFactory::getDbo();
$query1 = "SELECT a.id as cId, a.title, a.parent_id,a.level FROM `categories` AS a WHERE ( a.title LIKE '%keyword%' )";
$result1 = $db->setQuery($query1)->loadObjectlist(); //gives selected records

$query2 = "SELECT b.id as indId, b.indicator , b.cat_id, b.subcat_id, b.section_id  FROM `indicator` as b WHERE ( b.indicator LIKE '%keyword%' )"; 
$result2 = $db->setQuery($query2)->loadObjectlist(); //gives selected records

$_items = array_merge($result1,$result2); //then using $_items in php code to display the data

它在 Joomla 中,但我只想知道如何将这两个查询合并为一个。我尝试了以下方法,但它给出了类别表中第一个查询的结果。

(SELECT id as cId, title, parent_id,level, NULL FROM `categories`  WHERE ( title LIKE '%birth%' )) 
      UNION ALL 
(SELECT id as indId, indicator , cat_id, subcat_id, section_id FROM `indicator` WHERE ( indicator LIKE '%birth%' ))

期望的输出:

+------+-------------+------------+--------+--------+----------------+--------+-----------+----------+
| cId  | title       | parent_id  | level  | indId  | indicator      | cat_id | subcat_id | section_id
+------+-------------+------------+--------+--------+----------------+--------+-----------+----------+
| 2874 | births      |   2703     | 2      |  null  |   null         |  null  |   null    | null     |
+------+-------------+------------+--------+--------+----------------+--------+-----------+----------+
| 13   | birth weight|   12       | 3      |   null |   null         | null   |  null     | null     |
+------+-------------+------------+--------+--------+----------------+--------+-----------+----------+
| null |  null       |    null    |  null  | 135    | resident births|   23   |     25    |     1    |
+------+-------------+------------+--------+--------+----------------+--------+-----------+----------+
| null |  null       |    null    |  null  | 189    | births summary |   23   |     25    |     1    |
+------+-------------+------------+--------+--------+----------------+--------+-----------+----------+

以上输出将有助于获得正确的分页记录。我尝试使用 join,但 JOIN 需要 ON clause 中的公共列。在这里,我想要所有的列和它们的值。基本上我想在一个查询中组合 2 个表记录。任何帮助将不胜感激

【问题讨论】:

使用JOIN查询的概念 我想到了,但加入需要任何公用列,而这里我没有任何公用列。我想要所有的列 【参考方案1】:

这是一个例子,

有多种方法可以做到这一点,具体取决于您真正想要什么。没有通用栏目,你需要决定是要引入通用栏目还是要产品。

假设你有两张桌子:

parts:              custs:
+----+----------+   +-----+------+
| id | desc     |   |  id | name |
+----+----------+   +-----+------+
|  1 | Sprocket |   | 100 | Bob  |
|  2 | Flange   |   | 101 | Paul |
+----+----------+   +-----+------+

忘记实际的列,因为在这种情况下您很可能拥有客户/订单/零件关系;我刚刚使用这些列来说明如何做到这一点。

笛卡尔积将第一个表中的每一行与第二个表中的每一行匹配:

> select * from parts, custs;
      id desc     id  name
      -- ----     --- ----
      1  Sprocket 101 Bob
      1  Sprocket 102 Paul
      2  Flange   101 Bob
      2  Flange   102 Paul

这可能不是您想要的,因为 1000 个零件和 100 个客户会导致 100,000 行包含大量重复信息。

或者,您可以使用联合来仅输出数据,但不能并排(您需要确保两个选择之间的列类型兼容,方法是使表列兼容或强制它们在选择中):

> select id as pid, desc, '' as cid, '' as name from parts
  union
  select '' as pid, '' as desc, id as cid, name from custs;
    pid desc     cid name
    --- ----     --- ----
                 101 Bob 
                 102 Paul
    1   Sprocket
    2   Flange

在某些数据库中,您可以使用 rowid/rownum 列或伪列来并排匹配记录,例如:

id desc     id  name
-- ----     --- ----
1  Sprocket 101 Bob
2  Flange   101 Bob

代码类似于:

select a.id, a.desc, b.id, b.name
from parts a, custs b
where a.rownum = b.rownum;

它仍然笛卡尔积,但where 子句限制了行组合以形成结果的方式(所以根本不是笛卡尔积,真的)。

我没有为此测试该 SQL,因为它是我选择的 DBMS 的限制之一,因此,我认为在经过适当考虑的架构中永远不需要它。由于 SQL 不保证其生成数据的顺序,因此每次执行查询时匹配都会发生变化,除非您有 特定 关系或 order by 子句。

我认为理想的做法是在两个表中添加一列,指定关系是什么。如果没有真正的关系,那么您可能没有必要将它们与 SQL 并排放置。

【讨论】:

谢谢!您解释的联合查询帮助我解决了我的问题。我没有为其他表使用虚拟列,因此问题来了。为了他人的利益,我将发布我的正确查询【参考方案2】:

正如@Sinto 建议的union 的答案和下面的虚拟列名是整个正确的查询:

(SELECT id as cId, title, parent_id,level, NULL as indId, NULL as indicator , NULL as cat_id, NULL as subcat_id, NULL as section_id FROM `jm_categories` WHERE ( title LIKE '%births%' )) UNION ALL (SELECT NULL as cId, NULL as title, NULL as parent_id,NULL as level, id as indId, indicator , cat_id, subcat_id, section_id FROM `jm_indicator_setup` WHERE ( indicator LIKE '%births%' ))

我们必须匹配两个表中的列名,以便我们将记录作为一个组合。

【讨论】:

以上是关于单个查询从具有不同列的多个表中获取记录的主要内容,如果未能解决你的问题,请参考以下文章

是否有任何其他选项可以从表中获取总计数和同一查询中列的不同计数?

如何使用sql从具有不同列的两个表中获取不同的记录

合并来自谷歌表格列的记录

在一个查询Access数据库中从具有不同字段的两个不同表中选择列

如何获取具有相同app_id列但不同手机号码列的下一条记录

sql server 查询 order by 与 union 并替换多个列的空值