【问题标题】:Dynamic JOIN in MySQLMySQL中的动态连接
【发布时间】:2019-07-05 14:45:24
【问题描述】:

假设我有一个查询 -

Create Temporary Table myparams AS (
SELECT 'xyz' AS Column1
);

SELECT * FROM MyTable x
JOIN myparams y ON x.Column1 = y.Column1

这非常有效。但是,假设我这样做:

Create Temporary Table myparams AS (
SELECT NULL AS Column1
);

我在这里要做的是,当params 中有NULL 时,我想在加入MyTable 时返回所有行。

类似这样的:

SELECT * From MyTable x
IF(myparams.Column1 IS NULL, LEFT JOIN myparams.Column1 = x.Column1, 
INNER JOIN myparams.Column1 = x.Column1)

我问这个是因为我有一个存储过程,它接受可以有值的参数或NULL,我不想使用find_in_set,因为它逐行评估,在处理大量数据时效率低下数据。

编辑问题,因为我不清楚params 表。输入参数可以是逗号分隔的文本。所以参数没有一个单一的值。

前 -

Input params - `000-0000`, 1111-2222`

So currently I do this:

SELECT * FROM MyTable
find_in_set(MyTable.Column1, InputParams)

这会评估每一行,这对于 25 M 行来说效率非常低。

我想用所有输入参数创建一个临时表,然后加入 MyTable

【问题讨论】:

  • LEFT JOIN 单独执行完全相同的操作。无论是否匹配,它仍然会获取您的左侧表。
  • 不,不是那样。我并不总是需要完整的左表。如果有一个值而不是NULL,那么它应该从MyTable 中提取它,如果什么都不存在,那么它应该返回空集
  • 那我不知道你为什么要使用临时表或联接。只需使用SELECT * FROM MyTable x WHERE x.Column1 = ? 并为其提供过程参数。如果该参数为 NULL,它将返回空集,因为没有任何东西等于 NULL,甚至不是另一个 NULL。
  • 如果您有其他行为,您需要编辑上面的问题并显示一些示例数据以及您想要的结果。到目前为止,您的问题还不清楚。
  • 我会忘记使用存储过程。相反,编写应用程序代码以使用 IN (...) 谓词进行动态 SQL 查询,并为逗号分隔列表中的每个元素注入一个参数。请参阅我对stackoverflow.com/a/23941328/20860 的回答中的示例

标签: mysql join left-join inner-join


【解决方案1】:
WITH myparams AS (
SELECT null AS Column1
)
SELECT *
FROM MyTable x
INNER JOIN myparams y 
     ON x.Column1 IN (SELECT * FROM STRING_SPLIT(y.Column1,','))
          OR y.Column1 IS NULL

上面返回表'MyTable'的所有值,下一个只查询Column1是'a'或'b'的那些

WITH myparams AS (
SELECT 'a,b' AS Column1
)
SELECT *
FROM MyTable x
INNER JOIN myparams y 
     ON x.Column1 IN (SELECT * FROM STRING_SPLIT(y.Column1,','))
          OR y.Column1 IS NULL

还有第三种选择:

WITH myparams AS (
SELECT 'a,b' AS Column1
)
SELECT *
FROM MyTable x
INNER JOIN myparams y 
     ON x.Column1 = (SELECT value 
                     FROM STRING_SPLIT((SELECT ISNULL(Column1,'') 
                                        FROM myparams),',') 
                     WHERE value=x.Column1)
          OR (SELECT top 1 value 
              FROM STRING_SPLIT((SELECT ISNULL(Column1,'') 
                                 FROM myparams),',')) = ''

我没有大型数据集,但是这第三个选项的性能应该是最好的。

【讨论】:

  • 编辑了问题。参数可以是逗号分隔的输入
  • 编辑了我的答案以使用逗号分隔的列表。
猜你喜欢
  • 2011-08-15
  • 1970-01-01
  • 2012-01-16
  • 1970-01-01
  • 2013-12-15
  • 2018-07-04
  • 2015-11-14
  • 1970-01-01
  • 2011-11-17
相关资源
最近更新 更多