mysql - 如何在 SQL 中连接多个需要按时间过滤的表?

标签 mysql sql

我正在尝试链接几个表。在大多数表格中,我的信息不是基于时间的。但在我的一张 table 上却是这样。

在这个“基于时间”的表中,我需要根据时间和日期获取价格,这意味着价格在数据库中定义的特定时间后将“有效”。因此,诸如特定日期的销售之类的事情是可以完成的。 这需要与所有 LEFT JOIN 配合使用编辑表。

不使用时间子句的 SQL 如下:

SELECT  
conf_mno.mcc AS mcc,
conf_mno.mnc AS mnc,
conf_mno.operator_name AS operator_name, 
conf_countries.country_prefix AS country_prefix,  
conf_countries.country_name AS country_name,
conf_mno_prefix.prefix AS operator_prefix,
conf_mno_price.currency AS currency,
conf_mno_price.price AS price

FROM conf_mno

LEFT JOIN conf_mno_prefix ON conf_mno.mcc = conf_mno_prefix.mcc AND conf_mno.mnc = conf_mno_prefix.mnc

LEFT JOIN conf_countries ON conf_mno.mcc = conf_countries.mcc

LEFT JOIN conf_mno_price ON conf_mno.mcc = conf_mno_price.mcc AND conf_mno.mnc = conf_mno_price.mnc

GROUP BY mcc, mnc, operator_name, country_prefix, country_name

但是,这仅获取表格顶部的价格。我需要它通过使用 WHERE conf_mno_price.valid_timestamp <= UTC_TIMESTAMP() 来获取底部的那个和ORDER BY conf_mno_price.valid_timestamp DESC为了得到底部的那个。

我尝试了几种使用 SELECT 子查询的方法SELECT内并添加此...它确实获取第一个运营商的最后有效价格,但它将其应用于所有其他运营商。

conf_countries
+-------------------------------------------+
|  mcc  |  country_prefix  |  country_name  |
+-------+------------------+----------------+
|  222  |  39              |  Italy         |
+-------------------------------------------+

conf_mno
+---------------------------------+
|  mcc  |  mnc  |  operator_name  |
+-------+-------+-----------------+
|  222  |  01   |  Telekom1       |
+---------------------------------+
|  222  |  02   |  Telekom2       |
+---------------------------------+
|  222  |  03   |  Telekom3       |
+---------------------------------+
|  222  |  04   |  Telekom4       |
+---------------------------------+
|  222  |  07   |  Telekom7       |
+---------------------------------+
|  222  |  10   |  Telekom10      |
+---------------------------------+

conf_mno_prefix
+--------------------------+
|  mcc  |  mnc  |  prefix  |
+--------------------------+
|  222  |  01   |  70      |
+--------------------------+
|  222  |  01   |  71      |
+--------------------------+
|  222  |  01   |  73      |
+--------------------------+
|  222  |  04   |  78      |
+--------------------------+
|  222  |  07   |  79      |
+--------------------------+

conf_mno_price
+-------+-------+------------+---------+-----------------------+
|  mcc  |  mnc  |  currency  |  price  |  valid_timestamp      |
+-------+-------+------------+---------+-----------------------+
|  222  |  01   |  EUR       |  0.020  |  2016-11-11 00:00:00  |
+-------+-------+------------+---------+-----------------------+
|  222  |  01   |  EUR       |  0.010  |  2016-11-20 00:00:00  |
+-------+-------+------------+---------+-----------------------+
|  222  |  01   |  EUR       |  0.015  |  2016-12-03 00:00:00  |
+-------+-------+------------+---------+-----------------------+
|  222  |  01   |  EUR       |  0.020  |  2016-12-05 00:00:00  |
+-------+-------+------------+---------+-----------------------+
|  222  |  01   |  EUR       |  0.019  |  2016-12-10 00:00:00  |
+-------+-------+------------+---------+-----------------------+
|  222  |  04   |  EUR       |  0.025  |  2016-11-21 00:00:00  |
+-------+-------+------------+---------+-----------------------+

mcc 是国家/地区 ID,mnc 是该国家/地区内的运营商代码

输出应该是这样的:

stdClass Object ( [mcc] => 222 [mnc] => 1 [operator_name] => Telekom1 [country_prefix] => 39 [country_name] => Italy [operator_prefix] => 70, 71, 73 [currency] => EUR [price] => 0.010)

stdClass Object ( [mcc] => 222 [mnc] => 4 [operator_name] => Telekom4 [country_prefix] => 39 [country_name] => Italy [operator_prefix] => 78 [currency] => EUR [price] => 0.025)

0.010 是运营商 1 的最后有效价格,0.025 是运营商 4 的最后有效价格 - 假设当前日期是 2016 年 12 月 2 日 00:01:00

如何获取所有信息链接信息,例如国家/地区名称和运营商名称以及运营商的前缀以及每个运营商的最新价格?

这可能吗?

I can easily solve this by doing a second query, but as this is something which is intended to run all the time and it will be taxing on my server so trying to avoid it.

<小时/>

conf_mno_price的示例数据:

INSERT INTO `conf_mno_price` (`unq_id`, `mcc`, `mnc`, `currency`, `price`, `valid_timestamp`, `created_timestamp`, `modified_timestamp`) VALUES
(1, 222, 1, 'EUR', '0.01000000', '2016-08-28 22:00:00', '2016-12-03 18:52:26', '2016-12-03 18:52:26'),
(2, 222, 2, 'EUR', '0.00800000', '2016-08-28 22:00:00', '2016-12-03 18:52:57', '2016-12-03 18:52:57'),
(3, 222, 4, 'EUR', '0.01100000', '2016-08-28 23:00:00', '2016-12-03 18:59:38', '2016-12-03 18:59:38'),
(4, 222, 3, 'EUR', '0.01200000', '2016-08-28 22:00:00', '2016-12-03 18:53:07', '2016-12-03 18:53:07'),
(5, 222, 1, 'EUR', '0.01600000', '2016-09-04 22:00:00', '2016-12-03 18:54:11', '2016-12-03 18:54:11'),
(6, 222, 2, 'EUR', '0.01000000', '2016-09-04 22:00:00', '2016-12-03 18:54:27', '2016-12-03 18:54:27'),
(7, 222, 1, 'EUR', '0.00800000', '2016-09-11 22:00:00', '2016-12-03 18:55:31', '2016-12-03 18:55:31'),
(8, 222, 4, 'EUR', '0.01100000', '2016-09-18 22:00:00', '2016-12-03 18:56:17', '2016-12-03 18:56:17'),
(9, 222, 2, 'EUR', '0.00900000', '2016-09-25 22:00:00', '2016-12-03 18:56:54', '2016-12-03 18:56:54'),
(10, 222, 3, 'EUR', '0.00800000', '2016-09-25 22:00:00', '2016-12-03 18:57:08', '2016-12-03 18:57:08'),
(11, 222, 1, 'EUR', '0.00700000', '2016-10-02 22:00:00', '2016-12-03 18:57:54', '2016-12-03 18:57:54'),
(12, 222, 3, 'EUR', '0.00600000', '2016-10-30 23:00:00', '2016-12-03 19:03:12', '2016-12-03 19:03:12'),
(13, 222, 4, 'EUR', '0.01000000', '2016-10-30 23:00:00', '2016-12-03 18:59:38', '2016-12-03 18:59:38');

最佳答案

我认为您的问题中有两件事需要单独处理,因为它们都很棘手。

第一个是获取最新时间戳的价格,而不是表中出现的第一个时间戳。为此,您在分组和子查询方面走在正确的轨道上,但它变得令人费解:

SELECT  
conf_mno.mcc AS mcc,
conf_mno.mnc AS mnc,
conf_mno.operator_name AS operator_name, 
conf_countries.country_prefix AS country_prefix,  
conf_countries.country_name AS country_name,
conf_mno_prefix.prefix AS operator_prefix,
t2.currency AS currency,
t2.price AS price

FROM conf_mno

LEFT JOIN conf_mno_prefix ON conf_mno.mcc = conf_mno_prefix.mcc AND conf_mno.mnc = conf_mno_prefix.mnc
LEFT JOIN conf_countries ON conf_mno.mcc = conf_countries.mcc
INNER JOIN 
   (SELECT t.mcc,t.mnc,t.currency,t.price,t.valid_timestamp from 
       (select * from conf_mno_price where valid_timestamp<=UTC_TIMESTAMP() order by valid_timestamp DESC) t 
   group by mcc,mnc) t2 ON conf_mno.mcc = t2.mcc AND conf_mno.mnc = t2.mnc 
;

你所拥有的是一个JOIN内的SELECT内的SELECT。

  • 最里面的 SELECT 按时间戳对 conf_mno_table 进行排序,以便 第一个是您想要的:最新的
  • 另一个选择是 conf_mno_table 中的分组,以便您获得以下列表 不同的运营商。
  • 然后将其与其余部分连接起来,但要小心 因为你使用 LEFT 连接,这会离开你 一堆包含 NULL 字段的行 conf_mno_prices 表。你需要一个 INNER JOIN 来确保 连接两侧都匹配。
<小时/>
+------+------+---------------+----------------+--------------+-----------------+----------+-------+
| mcc  | mnc  | operator_name | country_prefix | country_name | operator_prefix | currency | price |
+------+------+---------------+----------------+--------------+-----------------+----------+-------+
|  222 |    1 | Telekom1      |             39 | Italy        |              70 | EUR      |  0.01 |
|  222 |    1 | Telekom1      |             39 | Italy        |              71 | EUR      |  0.01 |
|  222 |    1 | Telekom1      |             39 | Italy        |              73 | EUR      |  0.01 |
|  222 |    4 | Telekom4      |             39 | Italy        |              78 | EUR      | 0.025 |
+------+------+---------------+----------------+--------------+-----------------+----------+-------+

现在,如您所见,对于不同的 operator_prefix 值,您会获得不同的行。我相信从你的问题中你只想得到两行这些值的串联。这很棘手,如果您想要这样做,您需要考虑一下 FOR XML 的创造性用法,例如 in this question 。如果这样做,您将添加最初在查询中的最终 GROUP BY。

关于mysql - 如何在 SQL 中连接多个需要按时间过滤的表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40921578/

相关文章:

php - 左连接位置

mysql - com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException : Table 'gogogo.chatMessage' doesn't exist

php - 如何在同一选择中使用 3 AND?

c# - 销售人员记录

SQL - 连接多个表

php - 直接消息的 MySql 查询

mysql - 多个插入索引

php - 从最后插入的行获取最后插入的 id

MySQL - 从列中的两行返回多个条目的最新日期和总和

sql - 周四到周三的每周数据Sql查询