MySQL动态查询挑战 - 请帮助!

时间:2010-08-26 07:18:30

标签: database mysql dynamic-sql

我有这个问题:


   SELECT  
    userlist.USERID,  
    (case when (sum( CASE WHEN track.OFFER_ID = 221  THEN 1 ELSE 0 END) > 1) then 1 else 0 end) offer_211

FROM  
userlist  
INNER JOIN track ON userlist.USERID = track.USERID  

group by
userid

这是输出:

+------------+----------
| USERID     | offer_211 |
+------------+----------
| 1657487706 |         0 |  
| 1238439394 |         0 |  
| 1238427171 |         1 |  
| 1248431441 |         0 |  
| 1248464345 |         1 |  

此查询的目的:

有一个用户表,商品表和跟踪表。跟踪表包含用户表中的所有点击。我想创建一个如上所示的视图,它将向我显示用户对所有优惠的所有点击。如果用户点击某个商品,它将在该商品栏下显示“1”,否则会显示“0”。所有记录都来自轨道表。

以下是我需要帮助的地方: 我希望能够从“商品”表中动态创建“offer_211”列,而不是手动指定它们。(参见我的查询)

因此,对于用户点击或未点击(列)的所有优惠都将来自提供表格。

它应该是这样的:“offer _”+ offer.ID

它应该如下所示:(假设商品表中只有2个商品,ID为211,212)

商品表中可能有100个商品,因此此视图的动态列数应相同。

| USERID     | offer_211 | offer_212 |
+------------+----------+-------------
| 1657487706 |         0 |         1 |
| 1238439394 |         0 |         0 |
| 1238427171 |         1 |         0 |
| 1248431441 |         0 |         1 |
| 1248464345 |         1 |         0 |

跟踪表:

+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| ID         | int(22)     | NO   | PRI | NULL    | auto_increment |
| OFFER_ID   | int(22)     | YES  | MUL | NULL    |                |
| USERID     | int(22)     | YES  | MUL | NULL    |                |
+------------+-------------+------+-----+---------+----------------+

用户列表表:

+-------------+--------------+------+-----+---------+-------+
| Field       | Type         | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| USERID      | int(22)      | NO   | PRI | 0       |       |
| EMAIL       | varchar(200) | YES  |     | NULL    |       |
| FIRSTNAME   | varchar(100) | YES  |     | NULL    |       |
| LASTNAME    | varchar(100) | YES  |     | NULL    |       |

提供表:

+------------------+--------------+------+-----+-------------+----------------+
| Field            | Type         | Null | Key | Default     | Extra          |
+------------------+--------------+------+-----+-------------+----------------+
| ID               | int(11)      | NO   | PRI | NULL        | auto_increment |
| NAME             | varchar(100) | YES  |     | NULL        |                |
| DESCRIPTION      | text         | YES  |     | NULL        |                |
| URL              | text         | YES  |     | NULL        |                |

3 个答案:

答案 0 :(得分:1)

这种查询很快就会变得非常混乱。我建议使用更多标准查询来获取数据,然后在应用程序中处理这些数据。

但是,如果有一个非常好的理由来创建动态查询,这里有一种方法可以做 - 这些只是构建块,所以你需要修改它以满足你的要求:

使用CONCATGROUP_CONCAT构建一个SELECT语句,以便在prepared statement中使用:

SELECT CONCAT(
    'SELECT',
    GROUP_CONCAT(
        ' SUM(IF(offer_id = ', offer_id,
        ', 1, 0)) AS offer_', offer_id),
    ' FROM track;')
INTO @sql
FROM (SELECT DISTINCT offer_id FROM track) AS track;

以上命令创建的内容为:

SELECT @sql;

+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| @sql                                                                                                                                                                              |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| SELECT SUM(IF(offer_id = 1, 1, 0)) AS offer_1, SUM(IF(offer_id = 2, 1, 0)) AS offer_2, SUM(IF(offer_id = 3, 1, 0)) AS offer_3, SUM(IF(offer_id = 4, 1, 0)) AS offer_4 FROM track; |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

从动态SQL创建并执行预准备语句:

PREPARE stmt FROM @sql;
EXECUTE stmt;

+---------+---------+---------+---------+
| offer_1 | offer_2 | offer_3 | offer_4 |
+---------+---------+---------+---------+
|       3 |       2 |       1 |       1 |
+---------+---------+---------+---------+

DEALLOCATE PREPARE stmt;

答案 1 :(得分:0)

您是否考虑过获取用户ID和商品ID的列表,首先按用户ID排序,然后按商品ID排序?这是相同的信息,只是略有不同的组织,而且数据库执行像“select user_id,offer_id from track”这样的查询要快得多。

答案 2 :(得分:0)

麦克,

它返回的内容:最后看到它的切断方式 - 很奇怪。它可能是什么?

我也不明白你评论的最后部分 - 最后一个块;

Create and execute a prepared statement from the dynamic SQL:

PREPARE stmt FROM @sql;
EXECUTE stmt;

+---------+---------+---------+---------+
| offer_1 | offer_2 | offer_3 | offer_4 |
+---------+---------+---------+---------+
|       3 |       2 |       1 |       1 |
+---------+---------+---------+---------+

DEALLOCATE PREPARE stmt;

以下是新查询:

SELECT CONCAT(
    'SELECT',
    GROUP_CONCAT(
        ' SUM(IF(OFFER_ID = ', offer_id,
        ', 1, 0)) AS offer_', offer_id),
    ' FROM track;')
INTO @sql
FROM (SELECT DISTINCT ID as OFFER_ID from offer where `STATUS`=1) AS track;

select @sql;

这是输出:

SELECT SUM(IF(OFFER_ID = 178,1,0))AS offer_178,SUM(IF(OFFER_ID = 234,1,0))AS offer_234,SUM(IF(OFFER_ID = 206,1,0))AS offer_206,SUM(IF(OFFER_ID = 213,1,0))AS offer_213,SUM(IF(OFFER_ID = 229,1,0))AS offer_229,SUM(IF(OFFER_ID = 220,1,0))AS offer_220, SUM(IF(OFFER_ID = 221,1,0))AS offer_221,SUM(IF(OFFER_ID = 222,1,0))AS offer_222,SUM(IF(OFFER_ID = 225,1,0))AS offer_225,SUM( IF(OFFER_ID = 226,1,0))AS offer_226,SUM(IF(OFFER_ID = 257,1,0))AS offer_257,SUM(IF(OFFER_ID = 259,1,0))AS offer_259,SUM(IF(IF) OFFER_ID = 258,1,0))AS offer_258,SUM(IF(OFFER_ID = 260,1,0))AS offer_260,SUM(IF(OFFER_ID = 228,1,0))AS offer_228,SUM(IF(OFFER_ID =) 230,1,0))AS offer_230,SUM(IF(OFFER_ID = 232,1,0))AS offer_232,SUM(IF(OFFER_ID = 233,1,0))AS offer_233,SUM(IF(OFFER_ID = 239, 1,0))AS offer_239,SUM(IF(OFFER_ID = 240,1,0))AS offer_240,SUM(IF(OFFER_ID = 241,1,0))AS offer_241,SUM(IF(OFFER_ID = 242,1, 0))AS offer_242,SUM(IF(OFFER_ID = 243, 1,0))AS offer_243, SUM(IF(OFFE FROM track;