我有一个检查数据库的查询,以查看客户是否每天多次访问过。如果有,它会计算访问次数,然后告诉我他们访问的次数。问题是它将“Tickets.lcustomerid”抛入group by子句,导致我错过5条记录(没有条形码的客户)。如何更改以下查询以从group by子句中删除“tickets.lcustomerid”...如果我删除它我会收到一个错误告诉我“Tickets.lCustomerID”不是有效选择,因为它不是聚合或groupby子句。
有效的查询:
SELECT Customers.sBarcode, CAST(FLOOR(CAST(Tickets.dtCreated AS FLOAT)) AS DATETIME) AS dtCreatedDate, COUNT(Customers.sBarcode) AS [Number of Scans],
MAX(Customers.sLastName) AS LastName
FROM Tickets INNER JOIN
Customers ON Tickets.lCustomerID = Customers.lCustomerID
WHERE (Tickets.dtCreated BETWEEN @startdate AND @enddate) AND (Tickets.dblTotal <= 0)
GROUP BY Customers.sBarcode, CAST(FLOOR(CAST(Tickets.dtCreated AS FLOAT)) AS DATETIME)
HAVING (COUNT(*) > 1)
ORDER BY dtCreatedDate
输出是:
sBarcode dtcreated Date Number of Scans slastname
1234 1/4/2013 12:00:00 AM 2 Jimbo
1/5/2013 12:00:00 AM 3 Jimbo2
1578 1/6/2013 12:00:00 AM 3 Jimbo3
我当前使用子查询查询
SELECT customers.sbarcode,
Max(customers.slastname) AS LastName,
Cast(Floor(Cast(tickets.dtcreated AS FLOAT)) AS DATETIME) AS
dtCreatedDate,
Count(customers.sbarcode) AS
[Number of Scans],
Stuff ((SELECT ', '
+ RIGHT(CONVERT(VARCHAR, dtcreated, 100), 7) AS [text()]
FROM tickets AS sub
WHERE ( lcustomerid = tickets.lcustomerid )
AND ( dtcreated BETWEEN Cast(Floor(Cast(tickets.dtcreated
AS
FLOAT)) AS
DATETIME
)
AND
Cast(Floor(Cast(tickets.dtcreated
AS FLOAT
)) AS
DATETIME
)
+ '23:59:59' )
AND ( dbltotal <= '0' )
FOR xml path('')), 1, 1, '') AS [Times Scanned]
FROM tickets
INNER JOIN customers
ON tickets.lcustomerid = customers.lcustomerid
WHERE ( tickets.dtcreated BETWEEN @startdate AND @enddate )
AND ( tickets.dbltotal <= 0 )
GROUP BY customers.sbarcode,
Cast(Floor(Cast(tickets.dtcreated AS FLOAT)) AS DATETIME),
tickets.lcustomerid
HAVING ( Count(*) > 1 )
ORDER BY dtcreateddate
当前输出(注意没有条形码的记录丢失)是:
sBarcode dtcreated Date Number of Scans slastname Times Scanned
1234 1/4/2013 12:00:00 AM 2 Jimbo 12:00PM, 1:00PM
1578 1/6/2013 12:00:00 AM 3 Jimbo3 03:05PM, 1:34PM
答案 0 :(得分:1)
更新:基于我们的“聊天”,似乎customerid不是唯一的字段,但条形码是,即使客户ID是主键。
因此,为了不在子查询中使用GROUP BY客户ID,您需要加入第二个客户表,以便实际加入条形码。
试试这个:
SELECT customers.sbarcode,
Max(customers.slastname) AS LastName,
Cast(Floor(Cast(tickets.dtcreated AS FLOAT)) AS DATETIME) AS
dtCreatedDate,
Count(customers.sbarcode) AS
[Number of Scans],
Stuff ((SELECT ', '
+ RIGHT(CONVERT(VARCHAR, dtcreated, 100), 7) AS [text()]
FROM tickets AS subticket
inner join
customers as subcustomers
on
subcustomers.lcustomerid = subticket.lcustomerid
WHERE ( subcustomers.sbarcode = customers.sbarcode )
AND ( subticket.dtcreated BETWEEN Cast(Floor(Cast(tickets.dtcreated
AS
FLOAT)) AS
DATETIME
)
AND
Cast(Floor(Cast(tickets.dtcreated
AS FLOAT
)) AS
DATETIME
)
+ '23:59:59' )
AND ( dbltotal <= '0' )
FOR xml path('')), 1, 1, '') AS [Times Scanned]
FROM tickets
INNER JOIN customers
ON tickets.lcustomerid = customers.lcustomerid
WHERE ( tickets.dtcreated BETWEEN @startdate AND @enddate )
AND ( tickets.dbltotal <= 0 )
GROUP BY customers.sbarcode,
Cast(Floor(Cast(tickets.dtcreated AS FLOAT)) AS DATETIME)
HAVING ( Count(*) > 1 )
ORDER BY dtcreateddate
答案 1 :(得分:1)
我无法直接解决您的问题,因为我不了解您的数据模型或您尝试使用此查询完成的任务。但是,我可以就如何自己解决问题给你一些建议。
首先,您是否完全了解您要完成的工作以及表格如何组合在一起?如果是这样的话,请继续进行下一步,如果没有,请先了解这些知识,如果没有这种理解,就无法进行复杂的查询。
接下来分解您要完成的步骤,并确保在完成剩下的工作之前先让每个人完成任务。所以在你的情况下,你似乎错过了一些客户。从一个新的查询开始(我很确定这个问题有多个问题)。所以从join和where子句开始。
我怀疑你可能需要从客户开始并离开加入门票(这会将条件移动到左边的连接处,因为它们在门票上)。无论是否有票,这都将为您提供所有客户。如果那不是您想要的,那么使用jon和where clasues(并在尝试解决问题时使用select *),直到您返回所需的确切客户记录集。在此阶段使用select *的原因是为了查看数据中可能导致您遇到问题的原因。这可能会告诉你如何修复。
通常我从一个连接开始,然后一次一个地添加where clasues,直到我知道我正在获得正确的初始记录集。如果您有多个联接,请及时执行一次联接,以了解突然开始的记录何时记录的记录多于或少于预期。
然后进入更复杂的部分。一次添加一个并检查结果。如果你突然从10条记录变为5条或15条,那么你可能遇到了问题。当您一次只执行一个步骤并遇到问题时,您确切知道导致问题的原因使得查找和修复更加容易。
BY BY对于彻底理解很重要。您必须拥有组中的每个非聚合字段,否则它将无法工作。将此视为法律,如万有引力定律。这不是你可以改变的。但是,它可以通过使用派生表或CTE来解决。如果你不知道它们是什么,请仔细阅读它们,当你遇到复杂的东西并且你应该彻底理解它们时,它们是非常有用的技术。我怀疑你需要在这里使用派生表方法只对你需要的东西进行分组,然后将该派生表连接到其余的查询以获取ontehr字段。我将举一个简单的例子:
select
t1.table1id
, t1.field1
, t1.field2
, a.field3
, a.MostRecentDate
From table1 t1
JOIN
(select t1.table1id, t2.field3, max (datefield) as MostRecentDate
from table1 t1
JOin Table2 t2 on t1.table1id = t2.table1id
Where t2.field4 = 'test'
group by t1.table1id,t2.field3) a
ON a.table1id = t1.table1id
希望这种方法可以帮助您解决这个问题。