使用MySQL将值与表中的多列(在一个语句中)匹配

时间:2009-09-03 11:28:50

标签: sql mysql

我正在使用MySQL中的一个表,其中包含以下列:

id, january, february, march, april, etc

表中的数据如下所示:

aa, 0, 0, 1, 0
ab, 1, 0, 1, 0
ac, 1, 1, 0, 0
ad, 1, 1, 1, 0

要查询它,我可以轻松地执行此操作:

select * from table where january = 1 and february = 1

结果将是:

ac, 1, 1, 0, 0
ad, 1, 1, 1, 0

我想知道是否有办法这样做:

select * from table where table.columns = 1

我想在表达式中使用表列而不实际手动指定名称(键入它们)。

加分(+1)问题
可以像这样使用Match / Against来完成:

select * from table
where
(
    match (somehow,get,the,table,columns,I,need,here)
    against (1 in boolean mode)
)

感谢您的时间! :)

9 个答案:

答案 0 :(得分:4)

您必须使用Prepared Statement,因为您只想使用动态SQL来完成:

SET @stmt = 'SELECT * FROM YOUR_TABLE WHERE 1 = 1 '
SET @stmt = CONCAT(@stmt, (SELECT CONCAT_WS(' AND ', CONCAT(column_name, ' = 1 '))
                            FROM INFORMATION_SCHEMA.COLUMNS
                           WHERE table_name = 'YOUR_TABLE'
                             AND table_schema = 'db_name'
                             AND column_name NOT IN ('id'))); 

PREPARE stmt FROM @stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

第一个SET语句构造一个基本的SELECT语句; “1 = 1”部分就是为了更容易连接“AND column = 1

第二个SET语句将查询的内容连接起来,以便根据表名在第一个SET语句的字符串末尾获取列的列表。这个想法是这样的:

SELECT CONCAT_WS(' AND ', CONCAT(column_name, ' = 1 '))
  FROM INFORMATION_SCHEMA.COLUMNS
 WHERE table_name = 'YOUR_TABLE'
   AND table_schema = 'db_name'
   AND column_name NOT IN ('id')

...将返回类似“AND january = 1 AND february = 1 ...”的行。如果在WHERE子句中还有其他不需要的列,则必须更新NOT IN子句。

其余的只是标准的预备语句,这一切都必须在存储过程中进行。

答案 1 :(得分:1)

我明白史密斯先生正在努力做什么。

这是一个12行x 4列与1行x 12列的问题。

以前的表格设计类似于:

id,某人的身份,月份,每月x 12

1, 101, january, 1
2, 101, february, 1
3, 101, march, 0
etc..

对应的sql语句是:

$sqlQuery = "SELECT month FROM my_month_table WHERE value = 1";

我猜猜史密斯先生正在尝试:

id,某人的身份,1月,2月,3月......

$sqlQuery = "SELECT corrensponding_column_names_to_where_clause FROM my_month_table WHERE column_value = 1";

答案 2 :(得分:1)

你可以使用match ...对抗它。

在这种情况下,您的表必须是MyISAM表,您必须创建包含必需列的FULLTEXT索引。

答案 3 :(得分:1)

尝试创建视图

CREATE VIEW v_months 
AS 
SELECT *, CONCAT( CAST(jan AS CHAR(1)), 
                  CAST(feb AS CHAR(1)),
                  CAST(mar AS CHAR(1)),
                  ...) AS all 
FROM months

你会得到这样的东西:

aa, 0, 0, 1, 0, 0010
ab, 1, 0, 1, 0, 1010
ac, 1, 1, 0, 0, 1100
ad, 1, 1, 1, 0, 1110

然后你可以查询

SELECT * FROM v_months WHERE all = '100110010101'

或者,如果您想要查询“获取所有行,其中feb = 1”,您可以这样写:

SELECT * FROM v_months WHERE all LIKE '_1____________'    

其中'_'恰好匹配一个字符。

答案 4 :(得分:0)

您可以在MySQL中使用向量:

select * from table where (january, february) = (1, 1)

请注意文本列的不同服务器和客户端排序规则,然后您可能需要明确指定排序规则。

答案 5 :(得分:0)

在我看来,这是由于桌面设计看起来很糟糕(我猜这只是一个简单问题的例子,但请耐心等待,我认为这个概念可以更好地建模。
以下是表格:

  Things        Things_Months      Months
   thing_id       thing_id           Month_id
   thing_info     month_id           Month_Name
                  thing_month_id     order_field

这里是sql:

 select thing_info, month_name
  from things, things_months, months
  where things.thing_id = things_months.thing_id
    and things_months.month_id = months.month_id 
  order by things.things_info, months.order_field

结果将是

  thingy 1, January
  thingy 1, February
  thingy 2, April
  thingy 3, November
  thingy 3, December

答案 6 :(得分:0)

select * from table where 1 in (january, february)

答案 7 :(得分:0)

如何使用VIEW解决问题?

CREATE TABLE `d001ab05`.`months` (
`id` INT NOT NULL ,
`jan` BOOL NOT NULL ,
`feb` BOOL NOT NULL ,
`mar` BOOL NOT NULL ,
`apr` BOOL NOT NULL ,
`may` BOOL NOT NULL ,
`jun` BOOL NOT NULL ,
`jul` BOOL NOT NULL ,
`aug` BOOL NOT NULL ,
`sep` BOOL NOT NULL ,
`oct` BOOL NOT NULL ,
`nov` BOOL NOT NULL ,
`dec` BOOL NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = InnoDB;

插入数据:

INSERT INTO `d001ab05`.`months` (
`id`, `jan`, `feb`, `mar`, `apr`, `may`, `jun`,
`jul`, `aug`, `sep`, `oct`, `nov`, `dec`
) VALUES (
'1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'
), (
'2', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'
), (
'3', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'
), (
'4', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1'
);

使用选择查看:

CREATE OR REPLACE VIEW `moncase` AS
SELECT id,
CASE WHEN `jan` =1 OR `feb` =1 OR `mar` =1 OR `apr` =1 OR `may` =1 OR
`jun` =1 OR `jul` =1 OR `aug` =1 OR `sep` =1 OR `oct` =1 OR `nov` =1 OR `dec` =1
THEN 1 ELSE 0 END AS or_over_months
FROM months;

选择

SELECT * FROM `moncase` WHERE `or_over_months` = 1;

结果:

id | or_over_months
1  | 1
2  | 1
4  | 1

答案 8 :(得分:0)

您需要的是非转轴操作。 Microsoft SQL Server支持PIVOTUNPIVOT作为标准SQL的扩展。我不知道任何其他品牌的RDBMS支持内置的pivot / unpivot功能。当然MySQL不支持这个。

在这种情况下,您无法使用FULLTEXT搜索,因为作为文档say

  

全文索引只能与MyISAM表一起使用,并且只能为CHAR,VARCHAR或TEXT列创建。

并且无论如何都不会让您无需指定列,因为MATCH()谓词需要您在全文索引中列出所有列。

如果您无法重新构建表以存储每月行或单个列来编码所有12个月,那么您需要生成动态SQL。