0

I am facing issues trying to write a query. (this is slightly modified from my previous question)

My tables are laid out as follows:

 tblTicketIssues.TicketID
 tblTicketIssues.RequesterID

 tblPersonnelProfile.PersonnelID
 tblPersonnelProfile.FirstName
 tblPersonnelProfile.LastName

 tblTicketAttribute.TicketID
 tblTicketAttribute.Attribute
 tblTicketAttribute.AttributeValue

I have to display the following fields:

 TicketID, RequesterFullName, UrgentPriorityID, MediumPriorityID, 
 LowPrioritytID

This is the part that is challenging:

If tblTicketAttribute.Attribute= "Urgent" then the value from tblTicketAttribute.AttributeValue is displayed in UrgentPriority column

If tblTicketAttribute.Attribute= "Medium" then the value from tblTicketAttribute.AttributeValue is displayed in MediumPriority column

If tblTicketAttribute.Attribute= "Low" then the value from tblTicketAttribute.AttributeValue is displayed in LowPriority column

If tblTicketAttribute.Attribute= "Closed" then

The values in tblTicketAttribute.Attribute include "Urgent", "Medium", "Low", "Over30", "Over60", "Over90", "Closed"

I don't need to display all records. Only "Urgent", "Medium" & "Low".

4

4 回答 4

4

I'm not 100% sure that I understand, but I think this satisfies what you're asking for. Note that this was assuming that the database is MySQL, you didn't specify. The syntax of the IF() and CONCAT() may be slightly different if it's something else.

EDIT: updated query as per Csharp's "answer" below. MAX-ing the name is a bit of a hack.

SELECT t.TicketID,
    MAX(CONCAT(p.FirstName, ' ', p.LastName)) AS RequesterFullName,
    MAX(IF(a.Attribute = 'Urgent', a.AttributeValue, NULL)) AS UrgentPriorityID,
    MAX(IF(a.Attribute = 'Medium', a.AttributeValue, NULL)) AS MediumPriorityID,
    MAX(IF(a.Attribute = 'Low', a.AttributeValue, NULL)) AS LowPriorityID
FROM tblTicketIssues AS t
    LEFT JOIN tblPersonnelProfile AS p ON p.PersonnelID = t.RequesterID
    LEFT JOIN tblTicketAttribute AS a ON a.TicketID = t.TicketID
WHERE a.Attribute IN ('Urgent', 'Medium', 'Low')
GROUP BY t.TicketID;
于 2009-03-19T17:06:33.683 回答
2

数据库设计使用表的实体-属性-值模式tblTicketAttribute。您试图获得这个相当普通的查询结果所面临的困难表明 EAV 如何导致很多问题。

@Chad Birch的解决方案是获得结果的一种方法。这是获得所需结果的另一种方法:

SELECT t.TicketID,
    CONCAT(p.FirstName, ' ', p.LastName) AS RequesterFullName,
    a1.AttributeValue AS UrgentPriorityID,
    a2.AttributeValue AS MediumPriorityID,
    a3.AttributeValue AS LowPriorityID
FROM tblTicketIssues AS t
  JOIN tblPersonnelProfile AS p ON (p.PersonnelID = t.RequesterID)
  LEFT JOIN tblTicketAttribute AS a1 
    ON (a1.TicketID = t.TicketID AND a1.Attribute = 'Urgent')
  LEFT JOIN tblTicketAttribute AS a2 
    ON (a2.TicketID = t.TicketID AND a2.Attribute = 'Medium')
  LEFT JOIN tblTicketAttribute AS a3 
    ON (a3.TicketID = t.TicketID AND a3.Attribute = 'Low');

此解决方案不使用子句,但它确实需要为您要检索的每个属性GROUP BY单独设置。JOIN

另一个解决方案是在结果集的多行上获取属性:

SELECT t.TicketID,
    CONCAT(p.FirstName, ' ', p.LastName) AS RequesterFullName,
    a.AttributeValue AS AnyPriorityID
FROM tblTicketIssues AS t
  JOIN tblPersonnelProfile AS p ON (p.PersonnelID = t.RequesterID)
  LEFT JOIN tblTicketAttribute AS a 
    ON (a1.TicketID = t.TicketID AND a.Attribute IN ('Urgent', 'Medium', 'Low'));

该解决方案可以更好地作为 SQL 查询进行扩展,因为您不必在JOIN获取更多属性时添加更多子句。但这确实意味着您必须对应用程序代码中的结果集进行一些后处理,才能将其转换为您想要的格式。

于 2009-03-19T18:22:39.787 回答
1

I have no idea why you want to do it this way, but here goes (assuming SQL Server):

 SELECT TicketID, FirstName + ' ' + LastName AS RequestFullName,
 CASE WHEN Attribute = "Low" THEN AttributeValue ELSE "" END AS LowPriorityID,
 CASE WHEN Attribute = "Medium" THEN AttributeValue ELSE "" END AS MediumPriorityID,
 CASE WHEN Attribute = "Urgent" THEN AttributeValue ELSE "" END AS UrgentPriorityID
 FROM ...
 WHERE Attribute IN ("Urgent", "Low", "Medium")

But that seems like a bizarre way to do things to me.

Can you clarify if the relationship between tbTicketIssues and tbTicketAttributes is one-to-one, or one-to-many?

于 2009-03-19T17:09:29.870 回答
0

One relatively straightforward way to do something like this would be to just union three queries together. I suspect that what you're looking for would be something like this:

SELECT i.TicketID, a.FirstName, pp.AttributeValue AS UrgentPriorityID, null AS MediumPriorityID, null AS LowPrioritytID
FROM tblTicketIssues i, tblTicketAttribute a, tblPersonnelProfile pp
WHERE i.RequesterID = a.PersonnelID
AND i.TicketID = pp.TicketID
AND pp.Attribute = "Urgent"
UNION
SELECT i.TicketID, a.FirstName, null AS UrgentPriorityID, pp.AttributeValue AS MediumPriorityID, null AS LowPrioritytID
FROM tblTicketIssues i, tblTicketAttribute a, tblPersonnelProfile pp
WHERE i.RequesterID = a.PersonnelID
AND i.TicketID = pp.TicketID
AND pp.Attribute = "Medium"
UNION
SELECT i.TicketID, a.FirstName, null AS UrgentPriorityID, null AS MediumPriorityID, pp.AttributeValue AS LowPrioritytID
FROM tblTicketIssues i, tblTicketAttribute a, tblPersonnelProfile pp
WHERE i.RequesterID = a.PersonnelID
AND i.TicketID = pp.TicketID
AND pp.Attribute = "Low"

(this is SQL Server btw, though I doubt it would be much different on pretty much any RDBMS)

There are doubtless "slicker" ways that this could be done, but I like this way because it's very straightforward when reading it.

于 2009-03-19T17:12:47.490 回答