是否可以按声明反转一组?

时间:2012-02-21 16:56:44

标签: mysql

一个快速的MySQL问题。 如果我有一个以a | b | c | d | e | f | num列为例的表格 无论如何我可以做一些像SELECT a,b,..,f,sum(num)GROUP BY a,b,..,f 没有在后面按列表添加该组。我想要这样做的原因是我将有一个字段数组,我不想包含在组中,当它为空时我想按所有字段分组。

本质上如果我有一个包含(a,c,e)的数组 我想生成像这样的查询SELECT a,b,c,d,e,f,sum(num)作为num group by b,d,f 但是通过写一个像SELECT a,b,c,d,e,f,sum(num)group by inverse a,c,e,sum

是否存在这样的语法?

由于

1 个答案:

答案 0 :(得分:0)

不幸的是,你无法直接使用SQL。

但是,您可能希望使用information_schema.columns

尝试一些动态SQL
mysql> desc information_schema.columns;
+--------------------------+---------------------+------+-----+---------+-------+
| Field                    | Type                | Null | Key | Default | Extra |
+--------------------------+---------------------+------+-----+---------+-------+
| TABLE_CATALOG            | varchar(512)        | NO   |     |         |       |
| TABLE_SCHEMA             | varchar(64)         | NO   |     |         |       |
| TABLE_NAME               | varchar(64)         | NO   |     |         |       |
| COLUMN_NAME              | varchar(64)         | NO   |     |         |       |
| ORDINAL_POSITION         | bigint(21) unsigned | NO   |     | 0       |       |
| COLUMN_DEFAULT           | longtext            | YES  |     | NULL    |       |
| IS_NULLABLE              | varchar(3)          | NO   |     |         |       |
| DATA_TYPE                | varchar(64)         | NO   |     |         |       |
| CHARACTER_MAXIMUM_LENGTH | bigint(21) unsigned | YES  |     | NULL    |       |
| CHARACTER_OCTET_LENGTH   | bigint(21) unsigned | YES  |     | NULL    |       |
| NUMERIC_PRECISION        | bigint(21) unsigned | YES  |     | NULL    |       |
| NUMERIC_SCALE            | bigint(21) unsigned | YES  |     | NULL    |       |
| CHARACTER_SET_NAME       | varchar(32)         | YES  |     | NULL    |       |
| COLLATION_NAME           | varchar(32)         | YES  |     | NULL    |       |
| COLUMN_TYPE              | longtext            | NO   |     | NULL    |       |
| COLUMN_KEY               | varchar(3)          | NO   |     |         |       |
| EXTRA                    | varchar(27)         | NO   |     |         |       |
| PRIVILEGES               | varchar(80)         | NO   |     |         |       |
| COLUMN_COMMENT           | varchar(1024)       | NO   |     |         |       |
+--------------------------+---------------------+------+-----+---------+-------+
19 rows in set (0.05 sec)

假设您有一个表test.customers

mysql> desc test.customers;
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| companyname | varchar(30)  | YES  |     | NULL    |                |
| address     | varchar(40)  | YES  |     | NULL    |                |
| phone       | char(12)     | NO   |     | NULL    |                |
| email       | varchar(100) | YES  |     | NULL    |                |
| contact     | varchar(100) | YES  |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+
6 rows in set (0.02 sec)

这些列存在于information_schema.columns中。您可以使用以下方法检索它们:

SELECT GROUP_CONCAT(column_name) column_list FROM information_schema.columns
WHERE table_schema='test' AND table_name='customers';

它给你这个:

mysql> SELECT GROUP_CONCAT(column_name) column_list FROM information_schema.columns
    -> WHERE table_schema='test' AND table_name='customers';
+--------------------------------------------+
| column_list                                |
+--------------------------------------------+
| id,companyname,address,phone,email,contact |
+--------------------------------------------+
1 row in set (0.01 sec)

假设您希望获得所有内容(ID,公司名称,电话,电子邮件)。

您可以这样查询:

SELECT GROUP_CONCAT(A.column_name) column_list
FROM
(
    SELECT column_name
    FROM information_schema.columns
    WHERE table_schema='test'
    AND table_name='customers'
) A
LEFT JOIN
(
    SELECT 'id' column_name
    UNION SELECT 'companyname'
    UNION SELECT 'phone'
    UNION SELECT 'email'
) exclusion
USING (column_name)
WHERE exclusion.column_name IS NULL;

看看它给你的是什么:

mysql> SELECT GROUP_CONCAT(A.column_name) column_list
    -> FROM
    -> (
    ->     SELECT column_name
    ->     FROM information_schema.columns
    ->     WHERE table_schema='test'
    ->     AND table_name='customers'
    -> ) A
    -> LEFT JOIN
    -> (
    ->   SELECT 'id' column_name
    ->   UNION SELECT 'companyname'
    ->   UNION SELECT 'phone'
    ->   UNION SELECT 'email'
    -> ) exclusion
    -> USING (column_name)
    -> WHERE exclusion.column_name IS NULL;
+-----------------+
| column_list     |
+-----------------+
| address,contact |
+-----------------+
1 row in set (0.02 sec)

好的,你如何构建你正在寻找的查询?

让我们说

  • 您的表在mydb数据库中称为mytable
  • 它有列a,b,c,d,e,f,num
  • 你想对a,c,e,num
  • 执行反转

您必须动态构建查询。在这里:

步骤01)为a,c,e,num

创建排除列表
SELECT 'a' column_name
UNION SELECT 'c'
UNION SELECT 'e'
UNION SELECT 'num';

步骤02)创建查询以使用针对mydb.mytable的排除列表

SELECT GROUP_CONCAT(A.column_name) column_list
FROM
(
    SELECT column_name
    FROM information_schema.columns
    WHERE table_schema='mydb'
    AND table_name='mytable'
) A
LEFT JOIN
(
    SELECT 'a' column_name
    UNION SELECT 'c'
    UNION SELECT 'e'
    UNION SELECT 'num'
) exclusion
USING (column_name)
WHERE exclusion.column_name IS NULL;

步骤03)将输出捕获到变量(gbc按列分组)

SELECT GROUP_CONCAT(A.column_name)
INTO @gbc
FROM
(
    SELECT column_name
    FROM information_schema.columns
    WHERE table_schema='mydb'
    AND table_name='mytable'
) A
LEFT JOIN
(
    SELECT 'a' column_name
    UNION SELECT 'c'
    UNION SELECT 'e'
    UNION SELECT 'num'
) exclusion
USING (column_name)
WHERE exclusion.column_name IS NULL;

步骤04)创建完整查询

SET @s = CONCAT('SELECT a,b,c,d,e,f,sum(num) from mydb.mytable group by ',@gbc);

步骤05)执行动态SQL

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

试一试!!!

CAVEAT

如果您希望所有列按a,b,c,d,e,f分组,那么只需将其用作排除列表

SELECT GROUP_CONCAT(A.column_name)
INTO @gbc
FROM
(
    SELECT column_name
    FROM information_schema.columns
    WHERE table_schema='mydb'
    AND table_name='mytable'
) A
LEFT JOIN
(
    SELECT 'a' column_name
) exclusion
USING (column_name)
WHERE exclusion.column_name IS NULL;