Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL从特定的相关记录获取所有数据_Mysql_Join - Fatal编程技术网

MySQL从特定的相关记录获取所有数据

MySQL从特定的相关记录获取所有数据,mysql,join,Mysql,Join,我正在寻找一种在MySQL中为表中的每条记录输出所选相关记录的方法。我会进一步解释 我有两张表,分别是货币和汇率。这些表由一个货币代码字段连接,每个货币记录都有多个相关的汇率记录,每个汇率记录代表不同的一天。因此,货币和汇率之间存在着1:1的关系 我想从exchange\u rates表中检索每种货币的完整记录,但能够定义要选择的相关记录的特定条件。不仅是每种货币的最新汇率,还可能是每种货币的最新汇率记录,该记录包含标准\u x=NULL 很遗憾,您不能在派生表中使用LIMIT,否则类似的内容将

我正在寻找一种在MySQL中为表中的每条记录输出所选相关记录的方法。我会进一步解释

我有两张表,分别是货币汇率。这些表由一个货币代码字段连接,每个货币记录都有多个相关的汇率记录,每个汇率记录代表不同的一天。因此,货币和汇率之间存在着1:1的关系

我想从
exchange\u rates
表中检索每种货币的完整记录,但能够定义要选择的相关记录的特定条件。不仅是每种货币的最新汇率,还可能是每种货币的最新
汇率
记录,该记录包含
标准\u x=NULL

很遗憾,您不能在派生表中使用
LIMIT
,否则类似的内容将是一个简洁易读的解决方案

SELECT `currencies`.`currency_code`, `currencies`.`country`, `exchange_rates`.`id`,
       FROM_UNIXTIME(`exchange_rates`.`datestamp`), `rate` 
FROM `currencies` 
INNER JOIN (
SELECT `id`, `currency_code`, `invoice_id`, `datestamp`, `rate` 
FROM `exchange_rates` 
WHERE `criteria_x`=NULL AND `criteria_y` LIKE 'A' 
ORDER BY `datestamp` DESC
LIMIT 0, 1
) AS `exchange_rates` ON `currencies`.`currency_code`=`exchange_rates`.`currency_code`
ORDER BY `currencies`.`country`
LIMIT
子句应用于父查询,而不是派生表

这是我找到的唯一方法

SELECT `currencies`.`currency_code`, `currencies`.`country`, 
FROM_UNIXTIME( SUBSTRING_INDEX( SUBSTRING_INDEX(`exchange_rates`.`concat`, '-', 1), '-', -1)) AS `datestamp`,
SUBSTRING_INDEX( SUBSTRING_INDEX(`exchange_rates`.`concat`, '-', 2), '-', -1) AS `id`, 
SUBSTRING_INDEX( SUBSTRING_INDEX(`exchange_rates`.`concat`, '-', 3), '-', -1) AS `rate` 
FROM `currencies`
INNER JOIN (
SELECT `currency_code`, MAX(CONCAT_WS('-', `datestamp`, `id`, `rate`)) AS `concat`
FROM `exchange_rates` 
WHERE `criteria_x`=NULL AND `criteria_y` LIKE 'A' 
GROUP BY `exchange_rates`.`currency_code`
) AS `exchange_rates` ON `currencies`.`currency_code`=`exchange_rates`.`currency_code`
ORDER BY `currencies`.`country`
因此,将一组字段连接在一起,并在其上运行
MAX()
,以获取组内的排序顺序,然后使用
子字符串\u INDEX()
在父查询中解析这些字段。问题是,只有当我可以在连接字段上使用
MIN()
MAX()
时,此方法才有效。如果我想对一个字符串进行排序,或者按多个条件进行排序,但仅限于一条记录,那就不太理想了

此外,为了从关系数据库中获取所需的数据,不得不求助于可怕的字符串操作,这也给我带来了生理上的痛苦——必须有更好的方法


有人对更好的方法有什么建议吗?

试试这个查询。它预计工作良好,但如果你提供一些数据,我将能够做得很好

SELECT  `currencies`.`currency_code` as `CurrencyCode`,
    `currencies`.`country`, 
    FROM_UNIXTIME( SUBSTRING_INDEX( SUBSTRING_INDEX(`exchange_rates`.`concat`, '-', 1), '-', -1)) AS `datestamp`,
    SUBSTRING_INDEX( SUBSTRING_INDEX(`exchange_rates`.`concat`, '-', 2), '-', -1) AS `id`, 
    SUBSTRING_INDEX( SUBSTRING_INDEX(`exchange_rates`.`concat`, '-', 3), '-', -1) AS `rate`,
    (SELECT 
            MAX(CONCAT_WS('-', `datestamp`, `id`, `rate`)) AS `concat` 
            FROM `exchange_rates` 
            WHERE `criteria_x`= NULL 
            AND `criteria_y` LIKE 'A' 
            GROUP BY `exchange_rates`.`currency_code`
            HAVING `exchange_rates`.`currency_code` =`CurrencyCode`
    ) as `Concat`
FROM    `currencies`
ORDER BY `currencies`.`country` 

如果我正确理解了您的问题,您只需自行加入
汇率
即可选择利率:

SELECT   currencies.currency_code,
         currencies.country,
         exchange_rates.id,
         FROM_UNIXTIME(exchange_rates.datestamp),
         exchange_rates.rate
FROM     currencies
  JOIN   (
    SELECT   currency_code, MAX(datestamp) AS datestamp
    FROM     exchange_rates
    WHERE    criteria_x IS NULL AND criteria_y LIKE 'A'
    GROUP BY currency_code
  )   AS exchange_wantd USING (currency_code)
  JOIN   exchange_rates USING (currency_code, datestamp)
ORDER BY currencies.country

在尝试提供答案之前,有几个一般性问题需要(简要)讨论

您的第一个查询是:

SELECT `currencies`.`currency_code`, `currencies`.`country`, `exchange_rates`.`id`,
       FROM_UNIXTIME(`exchange_rates`.`datestamp`), `rate` 
FROM `currencies` 
INNER JOIN (
SELECT `id`, `currency_code`, `invoice_id`, `datestamp`, `rate` 
FROM `exchange_rates` 
WHERE `criteria_x`=NULL AND `criteria_y` LIKE 'A' 
ORDER BY `datestamp` DESC
LIMIT 0, 1
) AS `exchange_rates` ON `currencies`.`currency_code`=`exchange_rates`.`currency_code`
ORDER BY `currencies`.`country`
  • 我不认为你需要使用你正在使用的那么多。它们并不是完全错误,但我不会在我的答案中键入它们
  • SQL标准不认可
    标准\u x=NULL
    符号;应该写为
    标准\u x为空
    。MySQL可能会允许它;只要您知道它是非标准的,您就可以使用它
  • 如果像“A”这样的标准
    不包含元字符(
    %
    在标准SQL中),则该标准是不合理的。你最好用简单的等式:
    ='A'

  • 你的问题是:

    我想从
    exchange\u rates
    表中检索每种货币的完整记录,但能够定义要选择的相关记录的特定条件。不仅是每种货币的最新汇率,还可能是具有
    条件\u x字段的每种货币的最新汇率为NULL

    因此,您希望为满足所需其他条件的每种货币选择最新的汇率记录。我们可以假设在汇率表中,
    currency\u code
    datestamp
    的组合存在唯一的约束;这意味着将始终最多有一个匹配行。您没有指定在没有匹配行的情况下应该显示什么;当然,内部联接不会列出该货币

    对于SQL查询,我通常分步骤构建和测试整个查询,向先前开发的查询中添加额外的材料,这些查询可以正常工作并产生正确的输出。如果它很简单和/或我收集了太多的傲慢,我会先尝试一个复杂的查询,但当(复仇女神)它不起作用时,我会回到构建和测试过程。将其视为测试驱动(查询)开发

    第1阶段:符合指定标准的汇率记录 阶段2:符合指定标准的每种货币的最近汇率时间 阶段3:符合指定条件的每种货币的最近汇率时间的汇率记录 阶段4:符合指定条件的每种货币的货币信息和最近汇率时间的汇率记录 这需要将货币表与上一个查询的输出连接起来:

    SELECT c.currency_code, c.country, r.id,
           FROM_UNIXTIME(r.datestamp), r.rate
      FROM currencies AS c 
      JOIN (SELECT x.id, x.currency_code, x.invoice_id, x.datestamp, x.rate 
              FROM exchange_rates AS x
              JOIN (SELECT currency_code, MAX(datestamp) AS datestamp
                      FROM exchange_rates 
                     WHERE criteria_x IS NULL AND criteria_y = 'A' 
                     GROUP BY currency_code
                   ) AS m
                ON x.currency_code = m.currency_code AND x.datestamp = m.datestamp
           ) AS r
        ON c.currency_code = r.currency_code
     ORDER BY c.country
    
    除了Oracle只允许将“
    )r
    ”而不是“
    )作为r
    ”用于表别名和使用来自_UNIXTIME()
    ,我相信这应该可以正确地用于您提到的几乎所有SQL DBMS的当前版本

    由于最终查询中未返回发票ID,因此我们可以从中间查询的选择列表中删除该ID。一个好的优化器可能会自动做到这一点

    如果要查看货币信息,即使没有与条件匹配的汇率,也需要将最外层查询中的联接更改为左联接(也称为左外部联接)。如果只想查看货币的子集,则可以在最后(最外层)查询阶段应用该筛选器,或者(如果筛选器基于汇率表中的可用信息,例如货币代码)在最内层子查询(效率最高)或中间子查询应用该筛选器(除非优化器意识到它可以将过滤器向下推到最里面的子查询,否则效率不高)

    正确性通常是首要标准;性能是次要标准。但是,问题中提到了性能。第一条规则是测量此处显示的“简单”查询。只有当这证明太慢时,您才需要进一步担心。当您确实需要担心时,您会检查查询计划,以查看是否存在,例如
    SELECT currency_code, MAX(datestamp) 
      FROM exchange_rates 
     WHERE criteria_x IS NULL AND criteria_y = 'A' 
     GROUP BY currency_code
    
    SELECT x.id, x.currency_code, x.invoice_id, x.datestamp, x.rate 
      FROM exchange_rates AS x
      JOIN (SELECT currency_code, MAX(datestamp) AS datestamp
              FROM exchange_rates 
             WHERE criteria_x IS NULL AND criteria_y = 'A' 
             GROUP BY currency_code
           ) AS m
        ON x.currency_code = m.currency_code AND x.datestamp = m.datestamp
    
    SELECT c.currency_code, c.country, r.id,
           FROM_UNIXTIME(r.datestamp), r.rate
      FROM currencies AS c 
      JOIN (SELECT x.id, x.currency_code, x.invoice_id, x.datestamp, x.rate 
              FROM exchange_rates AS x
              JOIN (SELECT currency_code, MAX(datestamp) AS datestamp
                      FROM exchange_rates 
                     WHERE criteria_x IS NULL AND criteria_y = 'A' 
                     GROUP BY currency_code
                   ) AS m
                ON x.currency_code = m.currency_code AND x.datestamp = m.datestamp
           ) AS r
        ON c.currency_code = r.currency_code
     ORDER BY c.country
    
    SELECT currency_code, MAX(datestamp) AS datestamp FROM exchange_rates GROUP BY currency_code
    
    (SELECT currency_code, MAX(datestamp) AS datestamp FROM exchange_rates GROUP BY currency_code) AS dates_we_want
    
    (SELECT currency_code, MAX(datestamp) AS datestamp FROM exchange_rates GROUP BY currency_code) AS dates_we_want, currencies AS c, exchange_rates AS er
    
    er.*
    
    SELECT er.*
    FROM
        (SELECT currency_code, MAX(datestamp) AS datestamp
           FROM exchange_rates GROUP BY currency_code
        ) AS dates_we_want,
        currencies AS c, exchange_rates AS er
    WHERE
        dates_we_want.currency_code=er.currency_core
    AND
        dates_we_want.currency_code=c.currency_core
    AND
        dates_we_want.datestamp=er.datestamp
    AND
        `criteria_x`=NULL AND `criteria_y` LIKE 'A'