SQL视图查询无效

时间:2014-04-03 22:06:41

标签: mysql sql database sql-view

这些是我的表格:

portal_users(id, first_name, last_name, email, ...,)
courses(id, name, location, capacity, ...,)
feedback_questions(id, question, ...,)
feedback_answers(id, answers, IDquestion, IDuser, IDcourse)

我想用这个来做一个观点:

course | first_name | last_name | IDuser | IDcourse | question_1 | answer_1 | question_2 | answer_2

到目前为止

CREATE VIEW feedback_answers_vw
as 
SELECT 
fa.id,
fa.answer,
fq.question,
pu.first_name,
pu.last_name,
    fa.IDuser,
fa.IDcourse
FROM    feedback_answers fa
INNER JOIN feedback_questions fq
    ON fa.IDquestion = fq.id
INNER JOIN portal_users pu
    ON fa.IDuser = pu.id
INNER JOIN courses cu
    on fa.IDcourse = cu.id
 GROUP BY
fa.IDcourse, fa.IDuser

这只显示一个问题及其答案,但不是所有属于同一课程和用户的问题。

我可以在SELECT语句中使用类似的东西对其进行硬编码

SELECT 
    fa.id,
    (select question
        from feedback_questions
        where id = 1) as question_1,
    (select question
        from feedback_questions
        where id = 2) as question_2,
    (select question
        from feedback_questions
        where id = 3) as question_3,
    pu.first_name,
    pu.last_name,
    fa.IDuser,
    fa.IDcourse

但我想以正确的方式做到这一点,所以每次添加问题时我都不会改变代码。

修改 这是我的表的数据示例:

**Portal users:**
1, tom, hanks, tom_hanks@example.com, ..., 
2, steven, spielberg, steven@example.com, ...,


**Courses:**
1, quality, california, 30
2, information technologies, texas, 24


**Questions:**
1, How did you find the course?, ...,
2, Do you want purchase order?, ...,


**Answers:**
1, Internet, 1, 1, 1
2, yes, 2, 1, 1
3, TV, 1, 2, 1,
4, no, 2, 2, 1,
5, Internet, 1, 1, 2
6, yes, 1, 1, 2

这是我想在视图中显示的数据示例:

course|first_name|last_name|IDuser|IDcourse|Question_1|Answer_1|Question_2|Answer_2

----------------------------------------------------------------------------------
quality | tom | hanks | 1 | 1 | How did you find the course? | Internet | Do you want purchase order? | yes

quality | steven | spielberg | 2 | 1 | How did you find the course? | TV |   Do you want purchase order? | no

Information technologies | tom | hanks | 1 | 2 How did you find the course? | Internet | Do you want purchase order? | yes

3 个答案:

答案 0 :(得分:0)

在发布了一些示例数据之后,很明显需要一个数据透视表(在access / excel中称为'交叉号')。我们可以使用一些案例陈述对选择进行硬编码以涵盖固定数量的问题,但每次添加或删除问题时都必须重新考虑该解决方案。 @drapp在下面有这样的解决方案。

但是,我们真正想要的是视图返回的列数随着问题数量的增长而缩小。不幸的是,mysql没有任何内置函数可以帮助我们构建一个。我在网上找到的最佳解决方案是http://www.artfulsoftware.com/infotree/qrytip.php?id=523。作者建议动态构建sql select语句然后执行它。它实际上是一个非常优雅的解决方案。

面对这个要求,我不会在SQL中做这项工作。我预见到的问题是,随着问题数量的增加,将返回越来越多的专栏;您的视图会很快变慢,最终会完全停止工作。我会尝试在sql之外转换数据,可能在etl工具,应用程序服务器或BI工具中。

或者,如果我有能力(我从来没有),我会切换数据库引擎。以下是来自其他引擎的三种解决方案,它们提供了用于创建数据透视表的工具:

答案 1 :(得分:0)

我们刚刚在DB Design课程中讨论过视图,而我的教授说你不能在VIEW语句中使用连接。我不记得为什么不,但你的问题看起来很熟悉。

答案 2 :(得分:0)

我不知道你是否真的需要它作为一个视图,这里是一个示例查询。

如果你看一下where子句的第一部分,它基于一个最小的问题ID = 1.然后我将它加入到课程表和portal_user表中以获取这些字段。由于反馈答案是第一个表格,我们可以立即得到答案,但也可以加入问题表格来获得问题。

现在,如何简单地扩展此查询以用于将来的问题?请注意LEFT-JOIN之后的反馈回答AGAIN,但这次作为别名" fa2" (feedback_answers2),JOIN子句基于相同的用户,相同的课程,但仅针对问题ID = 2.然后将fa2.questionID上的问题表连接到问题表(别名fq2)。然后另一个完全相同的设置,但问题3.所以在这里,我什么都不做,但使用相同的表,但只是不同的别名。他们都从问题1开始,如果有问题2,那么得到它...如果问题3,得到它,根据需要扩展,没有分组等等。

所以现在如果您只关心您感兴趣的单一课程,只需将其添加到最外层的WHERE子句中,其他任何内容都不需要更改。获取10个问题,复制/粘贴相应问题ID的LEFT-JOIN组件。

SELECT
      c.name as course,
      pu.first_name,
      pu.last_name,
      fa1.IDUser,
      fa1.IDCourse,
      fq1.question as question1,
      fa1.answers as answer1,
      fq2.question as question2,
      fa2.answers as answer2,
      fq3.question as question3,
      fa3.answers as answer3
   from
      feedback_answers fa1
         JOIN courses c
            ON fa1.IDCourse = c.id
         JOIN portal_users pu
            ON fa1.IDUser = pu.id
         JOIN feedback_questions fq1
            ON fa1.IDquestion = fq1.id

         LEFT JOIN feedback_answers fa2
            ON fa1.IDUser = fa2.IDUser
            AND fa1.IDCourse = fa2.IDCourse
            AND fa2.id = 2
            LEFT JOIN feedback_questions fq2
               ON fa2.IDquestion = fq2.id

         LEFT JOIN feedback_answers fa3
            ON fa1.IDUser = fa3.IDUser
            AND fa1.IDCourse = fa3.IDCourse
            AND fa2.id = 3
            LEFT JOIN feedback_questions fq3
               ON fa3.IDquestion = fq3.id

   where
      fa1.id = 1