【问题标题】:SQL with AND in the same column同一列中带有 AND 的 SQL
【发布时间】:2013-04-19 02:58:03
【问题描述】:

我有一个名为“values”的 mySQL 表:

values:

file | metadata | value
________________________
01   | duration | 50s
01   | size     | 150mo
01   | extension| avi
02   | duration | 20s
02   | extension| mkv
03   | duration | 20s
03   | extension| mpeg

用户将在 SQL 中创建自己的查询,如下所示:

SELECT file FROM values WHERE (metadata='duration' AND value='20s') AND (metadata='extension' AND value='mkv')

我知道这个查询不好,但我无法更改“值”表。我不知道如何在这些条件下获取 file_id..

有什么想法吗?

提前致谢!

【问题讨论】:

  • 你只想要文件ID而不重复
  • 尝试使用 OR 条件
  • 我认为 OP 想要查询“duration”和“extension”,就好像它们是列一样......对吧,Kib?
  • 我认为您想要满足 (metadata='duration' AND value='20s') 或 (metadata='extension' AND value='mkv') 的两个结果。不是吗?如果是,您将放置 AND 而不是 OR。
  • 是的,没有重复更好! @Fildor 你明白了!如果我使用 OR 条件,它将返回我 file_id 2 和 3(因为它们的持续时间 = 20 秒)

标签: mysql sql conditional-statements


【解决方案1】:

像这样:

SELECT file
FROM
(
  SELECT file,
    MAX(CASE WHEN metadata = 'duration' THEN value END) AS duration,
    MAX(CASE WHEN metadata = 'extension' THEN value END) AS extension
  FROM `values`
  WHERE metadata IN ('duration', 'extension') 
  GROUP BY file
) AS sub
WHERE duration = '20s' AND extension = 'mkv';

在这里查看它的实际效果:


更新

如果您想动态地执行此操作,并假设这些元数据名称存储在一个新的单独表中,那么您可以使用动态 sql 来执行此操作。像这样的:

SET @sql = NULL;
SET @cols = NULL;

SELECT
  GROUP_CONCAT(DISTINCT CONCAT('MAX(IF(m.metadata_name = ''',
      m.metadata_name, ''', v.value, 0)) AS ', '''',   m.metadata_name, '''')
  ) INTO @cols
FROM Metadata AS m;

SET @sql = CONCAT('
  SELECT 
    v.file, ', @cols ,'
  FROM `values` AS v
  INNER JOIN metadata AS m ON v.metadata_id = m.metadata_id
  GROUP BY v.file');

prepare stmt 
FROM @sql;

execute stmt;

Updated SQL Fiddle Demo

然后你可以把它放在一个存储过程中并用它来显示它们,或者以你想要的方式查询它们。

【讨论】:

  • 非常好,您使用的是“数据透视表”,不是吗?如果有许多可以更改(添加或删除元数据)的元数据,则很难使用,但我会使用它!谢谢!
  • @Kib' - 随时欢迎您 :) 是的,我正在旋转桌子。您可以将其放入为所有元数据动态执行此操作的存储过程中,然后直接将参数传递给它。这样会很容易。
  • ^^ !酷~!通过这种方式我很有趣,我将创建另一个表'metadata_name',它将动态填充此查询!再次感谢您。
  • @Kib' - 再次欢迎您 :) 查看我对动态版本的编辑,它将为您提供所有元数据名称作为列标题。
  • 这太棒了!你让我免于许多小时的工作!不幸的是我有一个问题:变量@cols 太短了;我的表元数据中有 150 多个元数据 ^^' .. 我尝试在 MySQL 文档中找到解决方案,也许您知道解决方案?如果我找到该怎么做,我会在这里发表评论
【解决方案2】:

试试这个

SELECT file FROM `values` 
WHERE (metadata='duration'  AND value='20s') 
OR    (metadata='extension' AND value='mkv')
  • VALUES 是 mysql 的保留关键字,周围使用反引号

编辑:

你应该有这样的桌子

 file | size | duration | extension |
  1   | 150mo|  50s     | avi
  2   | null |  20s     | mkv
  3   | null |  20s     | mpeg

那么你的查询将是

    select file from `values` where duration = '20s' and extension = 'mkv' 

    

【讨论】:

  • 它会返回给我 file_id 2 和 3,而 file_id 3 没有 extension=mkv :/
  • 这是一个解决方案,但我不能改变表格的结构(即使它对我来说更容易..)谢谢你!
【解决方案3】:

目前还不清楚您想要实现什么。我猜你想要“持续时间”和“20 秒”或“扩展”和“mkv”的所有结果。所以你应该用“OR”替换或中间的“AND”。

SELECT file FROM values WHERE (metadata='duration' AND value='20s') OR (metadata='extension' AND value='mkv')

【讨论】:

  • 抱歉不清楚,我想把这两个条件放在同一个文件上
【解决方案4】:
SELECT 
    v.file 
FROM values AS v 
WHERE (v.metadata='duration' AND v.value='20s') 
  OR (v.metadata='extension' AND v.value='mkv')

【讨论】:

  • 它会返回给我 file_id 2 和 3,而 file_id 3 没有 extension=mkv :/
【解决方案5】:

使用存在于第二个条件:

SELECT distinct file FROM values WHERE (metadata='duration' AND value='20s') AND
exists (  SELECT * FROM values as v2 where v2.metadata='extension' AND v2.value='mkv' and v2.file=values.file )

【讨论】:

  • 好主意,但是遇到很多情况会变得不好用?但感谢这个提示
猜你喜欢
  • 1970-01-01
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-10
  • 2011-04-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多