简体   繁体   English

MySQL从SQL查询创建灵活的视图

[英]Mysql Create Flexible View from SQL query

I had a lot of attempts now but nothing realy helps. 我现在做了很多尝试,但没有任何帮助。 I wannt to create a flexible View(if possible). 我希望创建一个灵活的View(如果可能)。 With the result of 2 tabels. 结果为2个表格。 Here is what i wannt : 这是我想要的:

Table Visitor: 表访客:

ID      Hash              created
1   sadasdasdasd    2017-02-24 08:31:37
2   123kipdösas3    2017-02-24 08:31:37
3   12oaskdasdap    2017-02-24 08:31:37
4   asdauihsuahs    2017-02-24 08:31:37

Table VisitorData 表VisitorData

id  vID   type          value                      created
1   1   First Name      Hans                2017-02-24 09:15:11
2   1   Last Name       Wurst               2017-02-24 09:15:11
3   1   Company         WDHUWDHUGMBGH       2017-02-24 09:15:11
4   1   E-Mail          asddas@asdsd.de     2017-02-24 09:15:11
5   1   Phone           123123              2017-02-24 09:15:11
6   1   Salutation      Mr                  2017-02-24 09:15:11
7   1   Type            qwes                2017-02-24 09:15:11

In the end i wannt my Table(view) to be like: 最后,我希望我的表(视图)像:

id  vID  First Name    Last Name      Company       E-Mail               Phone    Salutation   Type                     
1   1       Hans        Wurst        WDHUWDHUGMBGH   asddas@asdsd.de    123123       Mr         qwes     

the fact is that we dont know what can be in the VisitorData.type. 事实是,我们不知道VisitorData.type中可以包含什么。 so i cant just do 所以我不能做

CREATE VIEW DataVisitorView AS
  SELECT DataVisitor.id, DataVisitor.hash, 
    IF(DataVisitorValues.Type='First Name',DataVisitorValues.Value,null) AS First Name,
    IF(DataVisitorValues.Type='Last Name',DataVisitorValues.Value,null) AS Last Name  ,
    IF(DataVisitorValues.Type=' Company ',DataVisitorValues.Value,null) AS Company         ,
    IF(DataVisitorValues.Type='E-Mail',DataVisitorValues.Value,null) AS E-Mail,
    IF(DataVisitorValues.Type='Phone           ',DataVisitorValues.Value,null) AS Phone           ,
    IF(DataVisitorValues.Type='Salutation      ',DataVisitorValues.Value,null) AS Salutation      
 FROM `DataVisitor`
    LEFT JOIN `DataVisitorValues`
      ON `DataVisitor`.`id` = `DataVisitorValues`.`vID`

so i was thinking more about this 所以我在想更多

CREATE VIEW `DataVisitorView` AS
SELECT
  DataVisitorValues2.typ
FROM (`DataVisitor2`
  LEFT JOIN `DataVisitorValues2`
    ON `DataVisitor2`.`id` = `DataVisitorValues2`.`vID`)
Where `DataVisitor2`.`id` = `DataVisitorValues2`.`vID`

but this it totaly wrong i get a table with 但这完全是错误的我得到一张桌子

|typ|

First Name
Last Name
Company 
...

Is there any Solution for this? 有什么解决办法吗? I also used Php for the job but the table but automaticly update himself and a chrone job is nothing that helps here 我也用Php做这份工作,但是桌子却自动更新了,而chrone的工作对这里没有帮助

You cant create dynamic views or views with variables in it. 您无法创建动态视图或其中包含变量的视图。 So you need to dynamic query. 因此您需要动态查询。

Create table/insert data 创建表/插入数据

CREATE TABLE Visitor
    (`ID` INT, `Hash` VARCHAR(12), `created` VARCHAR(19))
;

INSERT INTO Visitor
    (`ID`, `Hash`, `created`)
VALUES
    (1, 'sadasdasdasd', '2017-02-24 08:31:37'),
    (2, '123kipdösas3', '2017-02-24 08:31:37'),
    (3, '12oaskdasdap', '2017-02-24 08:31:37'),
    (4, 'asdauihsuahs', '2017-02-24 08:31:37')
;


CREATE TABLE VisitorData
    (`id` INT, `vID` INT, `type` VARCHAR(10), `value` VARCHAR(15), `created` VARCHAR(19))
;

INSERT INTO VisitorData
    (`id`, `vID`, `type`, `value`, `created`)
VALUES
    (1, 1, 'First Name', 'Hans', '2017-02-24 09:15:11'),
    (2, 1, 'Last Name', 'Wurst', '2017-02-24 09:15:11'),
    (3, 1, 'Company', 'WDHUWDHUGMBGH', '2017-02-24 09:15:11'),
    (4, 1, 'E-Mail', 'asddas@asdsd.de', '2017-02-24 09:15:11'),
    (5, 1, 'Phone', '123123', '2017-02-24 09:15:11'),
    (6, 1, 'Salutation', 'Mr', '2017-02-24 09:15:11'),
    (7, 1, 'Type', 'qwes', '2017-02-24 09:15:11')
;

Query 询问

What you want is a output thats is called a pivot table. 您想要的是一个称为数据透视表的输出。 This is done with GROUP BY and using the function MAX like this. 这是通过GROUP BY并使用函数MAX来完成的。

SELECT 
   Visitor.id
 , VisitorData.vid
 , MAX(CASE WHEN VisitorData.type = 'First Name' THEN VisitorData.value ELSE NULL END) AS 'First_name'
 , MAX(CASE WHEN VisitorData.type = 'Last Name' THEN VisitorData.value ELSE NULL END) AS 'Last_Name'
 , MAX(CASE WHEN VisitorData.type = 'Company' THEN VisitorData.value ELSE NULL END) AS 'Company'
 , MAX(CASE WHEN VisitorData.type = 'E-Mail' THEN VisitorData.value ELSE NULL END) AS 'E-Mail'
 , MAX(CASE WHEN VisitorData.type = 'Phone' THEN VisitorData.value ELSE NULL END) AS 'Phone'
 , MAX(CASE WHEN VisitorData.type = 'Salutation' THEN VisitorData.value ELSE NULL END) AS 'Salutation'
 , MAX(CASE WHEN VisitorData.type = 'Type' THEN VisitorData.value ELSE NULL END) AS 'Type'
FROM 
 Visitor
INNER JOIN 
 VisitorData
ON
 Visitor.id = VisitorData.vid
GROUP BY 
   Visitor.id
 , VisitorData.vid
ORDER BY 
   Visitor.id
 , VisitorData.vid 

Result 结果

    id     vid  First_name  Last_Name  Company        E-Mail           Phone   Salutation  Type    
------  ------  ----------  ---------  -------------  ---------------  ------  ----------  --------
     1       1  Hans        Wurst      WDHUWDHUGMBGH  asddas@asdsd.de  123123  Mr          qwes    

To make the columns dynamic you can use this. 要使列动态化,您可以使用它。

SET SESSION group_concat_max_len = 1000000 -- enlarge GROUP_CONCAT output to 10 Mb
SET @group_concat_sql = NULL;

# generate all MAX lines 
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'MAX(CASE WHEN VisitorData.type = \'',VisitorData.type,'\' THEN VisitorData.value ELSE NULL END) AS \'',VisitorData.type,'\''      
    )
  )
    INTO @group_concat_sql
FROM
 VisitorData;

# generate complete SQL query
SET @sql = 
CONCAT(
 'SELECT 
     Visitor.id
   , VisitorData.vid
 '
 , ','
 , @group_concat_sql
 , 'FROM 
 Visitor
INNER JOIN 
 VisitorData
ON
 Visitor.id = VisitorData.vid
GROUP BY 
   Visitor.id
 , VisitorData.vid
ORDER BY 
   Visitor.id
 , VisitorData.vid 
'  
); 

# execute SQL query
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Result 结果

    id     vid  First Name  Last Name  Company        E-Mail           Phone   Salutation  Type    
------  ------  ----------  ---------  -------------  ---------------  ------  ----------  --------
     1       1  Hans        Wurst      WDHUWDHUGMBGH  asddas@asdsd.de  123123  Mr          qwes    

It looks as though you aren't going to have a lot of control over your data. 看来您对数据没有太多控制权。 I pretty much agree with @Raymond Nijland approach but I would add some code to bring a degree of control. 我非常同意@Raymond Nijland的方法,但是我会添加一些代码来带来一定程度的控制。 Start by creating a synonyms table. 首先创建同义词表。

drop table if exists synonym_table;
create table synonym_table (ordinalposition int, `type` varchar(10) , synonym varchar(10));
alter table synonym_table
    add key k001(`type`),
    add key k002(synonym);

This will allow you to standardise terms like Company and CO. For example 这将使您能够标准化公司和公司等术语。例如

truncate table visitordata;
INSERT INTO VisitorData
    (`id`, `vID`, `type`, `value`, `created`)
VALUES
    (1, 1, 'First Name', 'Hans', '2017-02-24 09:15:11'),
    (2, 1, 'Last Name', 'Wurst', '2017-02-24 09:15:11'),
    (3, 1, 'Company', 'WDHUWDHUGMBGH', '2017-02-24 09:15:11'),
    (4, 1, 'E-Mail', 'asddas@asdsd.de', '2017-02-24 09:15:11'),
    (5, 1, 'Phone', '123123', '2017-02-24 09:15:11'),
    (6, 1, 'Salutation', 'Mr', '2017-02-24 09:15:11'),
    (7, 1, 'Type', 'qwes', '2017-02-24 09:15:11'),
    (8, 2, 'FName', 'Hans', '2017-02-24 09:15:11'),
    (9, 2, 'Last Name', 'Wurst', '2017-02-24 09:15:11'),
    (10, 2, 'Co.', 'WDHUWDHUGMBGH', '2017-02-24 09:15:11')

insert into synonym_table (`type`,synonym) 
select distinct `type`,`type` from visitordata v order by id
on duplicate key update `type` = v.`type`;

Note the synonyms default to the type and the on duplicate key clause ensures uniqueness Now update known synonyms - note you will have to do this as often as necessary 请注意,同义词默认为类型,并且onplicate key子句可确保唯一性现在更新已知的同义词-请注意,您将必须根据需要经常执行此操作

update synonym_table
        set synonym = 'First Name' where `type` in('fname' , 'FirstName');

update synonym_table
    set synonym = 'Company' where `type` in('Co.' , 'Business', 'Agency');

MariaDB [sandbox]> select * from synonym_table;
+--------------+------------+------------+
| ordinalvalue | type       | synonym    |
+--------------+------------+------------+
|         NULL | First Name | First Name |
|         NULL | Last Name  | Last Name  |
|         NULL | Company    | Company    |
|         NULL | E-Mail     | E-Mail     |
|         NULL | Phone      | Phone      |
|         NULL | Salutation | Salutation |
|         NULL | Type       | Type       |
|         NULL | FName      | First Name |
|         NULL | Co.        | Company    |
+--------------+------------+------------+

Update the ordinalposition to control the order of the column headers. 更新ordinalposition以控制列标题的顺序。 Now adapt the code from raymond to use the synonym_table 现在修改雷蒙德的代码以使用synonym_table

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM