我们必须每周运行一次SQL Server查询,以考虑从最近的星期六00:01到星期六的23:59(科威特时间)开始的事务。该过程考虑了数千行,因此非常繁重。我决定分两个步骤进行操作,主要是因为我无法将其整合为一个;)
我首先必须将每个事务的SQL Server date列偏移到科威特时间。
由于我通过PHP使用此脚本,因此我分两个步骤进行操作:首先定义最新的星期六日期范围(例如,如果查询在星期六运行,它将计算前一个星期六的范围),然后在第二个脚本中使用变量。
在这里,我的第一个查询得到了最后一个星期六:
SELECT
(datetime, CASE
WHEN DATENAME(weekday, CAST(CURRENT_TIMESTAMP AS date)) = 'Sunday'
THEN DATEADD(DAY, -1, CAST(CURRENT_TIMESTAMP AS date))
WHEN DATENAME(weekday, CAST(CURRENT_TIMESTAMP AS date)) = 'Monday'
THEN DATEADD(DAY, -2, CAST(CURRENT_TIMESTAMP AS date))
WHEN DATENAME(weekday, CAST(CURRENT_TIMESTAMP AS date)) = 'Tuesday'
THEN DATEADD(DAY, -3, CAST(CURRENT_TIMESTAMP AS date))
WHEN DATENAME(weekday, CAST(CURRENT_TIMESTAMP AS date)) = 'Wednesday'
THEN DATEADD(DAY, -4, CAST(CURRENT_TIMESTAMP AS date))
WHEN DATENAME(weekday, CAST(CURRENT_TIMESTAMP AS date)) = 'Thursday'
THEN DATEADD(DAY, -5, CAST(CURRENT_TIMESTAMP AS date))
WHEN DATENAME(weekday, CAST(CURRENT_TIMESTAMP AS date)) = 'Friday'
THEN DATEADD(DAY, -6, CAST(CURRENT_TIMESTAMP AS date))
WHEN DATENAME(weekday, CAST(CURRENT_TIMESTAMP AS date)) = 'Saturday'
THEN DATEADD(DAY, -0, CAST(CURRENT_TIMESTAMP AS date))
END) at time zone 'Arab Standard Time' AS start_time,
CONVERT(datetime,
CASE
WHEN datename(weekday,cast(CURRENT_TIMESTAMP AS date)) = 'Sunday' THEN dateadd(day,0,cast(CURRENT_TIMESTAMP AS date))
WHEN datename(weekday,cast(CURRENT_TIMESTAMP AS date)) = 'Monday' THEN dateadd(day,-1,cast(CURRENT_TIMESTAMP AS date))
WHEN datename(weekday,cast(CURRENT_TIMESTAMP AS date)) = 'Tuesday' THEN dateadd(day,-2,cast(CURRENT_TIMESTAMP AS date))
WHEN datename(weekday,cast(CURRENT_TIMESTAMP AS date)) = 'Wednesday' THEN dateadd(day,-3,cast(CURRENT_TIMESTAMP AS date))
WHEN datename(weekday,cast(CURRENT_TIMESTAMP AS date)) = 'Thursday' THEN dateadd(day,-4,cast(CURRENT_TIMESTAMP AS date))
WHEN datename(weekday,cast(CURRENT_TIMESTAMP AS date)) = 'Friday' THEN dateadd(day,-5,cast(CURRENT_TIMESTAMP AS date))
WHEN datename(weekday,cast(CURRENT_TIMESTAMP AS date)) = 'Saturday' THEN dateadd(day,-6,cast(CURRENT_TIMESTAMP AS date))
END) at time zone 'Arab Standard Time' as end_time
然后我在上述另一个查询中插入来自上述查询的变量$ start_date和$ end_date以获取最终结果:
SELECT
USERID,
DEPOSIT,
RMwin,
CASE
WHEN DEPOSIT > 0
AND RMwin <= DEPOSIT
AND RMwin > 0 THEN
RMWIN * 0.3
WHEN RMwin > DEPOSIT
AND DEPOSIT > 0 THEN
DEPOSIT *.3
WHEN RMwin <= 0 THEN
0 ELSE 0
END AS CB,
CASE
WHEN DEPOSIT + RMwin = 0 THEN
0 ELSE 1
END AS check_,
FORMAT ( min_lt, 'dd/MM/yy HH:mm' ) AS min_lt,
format ( min_kuw, 'dd/MM/yy HH:mm' ) AS min_kuw,
format ( max_lt, 'dd/MM/yy HH:mm' ) AS max_lt,
format ( max_kuw, 'dd/MM/yy HH:mm' ) AS max_kuw,
min_id,
max_id
FROM
(
SELECT
UserID,
SUM ( DEPOSIT ) AS DEPOSIT,
SUM ( RMwin ) AS RMwin,
MIN ( AccountTranID ) AS min_id,
MAX ( AccountTranID ) AS max_id,
MIN ( local_time ) AS min_lt,
MIN ( kuwait_date ) AS min_kuw,
MAX ( local_time ) AS max_lt,
MAX ( kuwait_date ) AS max_kuw
FROM
(
SELECT
AccountTranID,
TranType,
UserID,
datetime,
datetime AT TIME ZONE 'Romance Standard Time' AS local_time,
datetime AT TIME ZONE 'Romance Standard Time' AT TIME ZONE 'Arab Standard Time' AS kuwait_date,
CASE
TranType
WHEN 'GAME_B' THEN
- AmountReal
WHEN 'GAME_W' THEN
- AmountReal
WHEN 'REFUND' THEN
- AmountReal ELSE 0
END AS RMwin,
CASE
WHEN TranType = 'DEPOSIT' THEN
AmountReal ELSE 0
END AS DEPOSIT
FROM
admin_all.DataFeed
WHERE
datetime AT TIME ZONE 'Romance Standard Time' AT TIME ZONE 'Arab Standard Time' >= ( convert(datetime,'".$start_date."') AT TIME ZONE 'Arab Standard Time' )
AND datetime AT TIME ZONE 'Romance Standard Time' AT TIME ZONE 'Arab Standard Time' < ( convert(datetime,'".$end_date."') AT TIME ZONE 'Arab Standard Time' )
) trans
GROUP BY
UserID
) ok
ORDER BY
CB DESC
不幸的是,此查询对于我们的服务器资源非常繁重,我正在尝试寻找一种简化它以达到相同结果的方法。
有人能解决这个问题吗?
答案 0 :(得分:0)
您的第一个查询可以这样简单(例如,(输出)示例为2020年8月):
declare @startdate datetime = '2020-08-01 00:00:00';
with testdates(d) as (
select @startdate as d
union all
select dateadd(day,1,d) from testdates where d<='2020-08-31')
select
d,
datepart(weekday,d),
datename(weekday,d),
dateadd(SECOND,1,dateadd(day,-(datepart(WEEKDAY,d)%7)-7,d)) start_time,
dateadd(day,-(datepart(WEEKDAY,d)%7),d) end_time
from testdates;
输出:
d start_time end_time
----------------------- ----------- ------------------------------ ----------------------- -----------------------
2020-08-01 00:00:00.000 7 Saturday 2020-07-25 00:00:01.000 2020-08-01 00:00:00.000
2020-08-02 00:00:00.000 1 Sunday 2020-07-25 00:00:01.000 2020-08-01 00:00:00.000
2020-08-03 00:00:00.000 2 Monday 2020-07-25 00:00:01.000 2020-08-01 00:00:00.000
2020-08-04 00:00:00.000 3 Tuesday 2020-07-25 00:00:01.000 2020-08-01 00:00:00.000
2020-08-05 00:00:00.000 4 Wednesday 2020-07-25 00:00:01.000 2020-08-01 00:00:00.000
2020-08-06 00:00:00.000 5 Thursday 2020-07-25 00:00:01.000 2020-08-01 00:00:00.000
2020-08-07 00:00:00.000 6 Friday 2020-07-25 00:00:01.000 2020-08-01 00:00:00.000
2020-08-08 00:00:00.000 7 Saturday 2020-08-01 00:00:01.000 2020-08-08 00:00:00.000
2020-08-09 00:00:00.000 1 Sunday 2020-08-01 00:00:01.000 2020-08-08 00:00:00.000
2020-08-10 00:00:00.000 2 Monday 2020-08-01 00:00:01.000 2020-08-08 00:00:00.000
2020-08-11 00:00:00.000 3 Tuesday 2020-08-01 00:00:01.000 2020-08-08 00:00:00.000
2020-08-12 00:00:00.000 4 Wednesday 2020-08-01 00:00:01.000 2020-08-08 00:00:00.000
2020-08-13 00:00:00.000 5 Thursday 2020-08-01 00:00:01.000 2020-08-08 00:00:00.000
2020-08-14 00:00:00.000 6 Friday 2020-08-01 00:00:01.000 2020-08-08 00:00:00.000
2020-08-15 00:00:00.000 7 Saturday 2020-08-08 00:00:01.000 2020-08-15 00:00:00.000
2020-08-16 00:00:00.000 1 Sunday 2020-08-08 00:00:01.000 2020-08-15 00:00:00.000
2020-08-17 00:00:00.000 2 Monday 2020-08-08 00:00:01.000 2020-08-15 00:00:00.000
2020-08-18 00:00:00.000 3 Tuesday 2020-08-08 00:00:01.000 2020-08-15 00:00:00.000
2020-08-19 00:00:00.000 4 Wednesday 2020-08-08 00:00:01.000 2020-08-15 00:00:00.000
2020-08-20 00:00:00.000 5 Thursday 2020-08-08 00:00:01.000 2020-08-15 00:00:00.000
2020-08-21 00:00:00.000 6 Friday 2020-08-08 00:00:01.000 2020-08-15 00:00:00.000
2020-08-22 00:00:00.000 7 Saturday 2020-08-15 00:00:01.000 2020-08-22 00:00:00.000
2020-08-23 00:00:00.000 1 Sunday 2020-08-15 00:00:01.000 2020-08-22 00:00:00.000
2020-08-24 00:00:00.000 2 Monday 2020-08-15 00:00:01.000 2020-08-22 00:00:00.000
2020-08-25 00:00:00.000 3 Tuesday 2020-08-15 00:00:01.000 2020-08-22 00:00:00.000
2020-08-26 00:00:00.000 4 Wednesday 2020-08-15 00:00:01.000 2020-08-22 00:00:00.000
2020-08-27 00:00:00.000 5 Thursday 2020-08-15 00:00:01.000 2020-08-22 00:00:00.000
2020-08-28 00:00:00.000 6 Friday 2020-08-15 00:00:01.000 2020-08-22 00:00:00.000
2020-08-29 00:00:00.000 7 Saturday 2020-08-22 00:00:01.000 2020-08-29 00:00:00.000
2020-08-30 00:00:00.000 1 Sunday 2020-08-22 00:00:01.000 2020-08-29 00:00:00.000
2020-08-31 00:00:00.000 2 Monday 2020-08-22 00:00:01.000 2020-08-29 00:00:00.000
2020-09-01 00:00:00.000 3 Tuesday 2020-08-22 00:00:01.000 2020-08-29 00:00:00.000
答案 1 :(得分:0)
With DateRange As
(SELECT
(datetime, CASE
WHEN DATENAME(weekday, CAST(CURRENT_TIMESTAMP AS date)) = 'Sunday'
THEN DATEADD(DAY, -1, CAST(CURRENT_TIMESTAMP AS date))
WHEN DATENAME(weekday, CAST(CURRENT_TIMESTAMP AS date)) = 'Monday'
THEN DATEADD(DAY, -2, CAST(CURRENT_TIMESTAMP AS date))
WHEN DATENAME(weekday, CAST(CURRENT_TIMESTAMP AS date)) = 'Tuesday'
THEN DATEADD(DAY, -3, CAST(CURRENT_TIMESTAMP AS date))
WHEN DATENAME(weekday, CAST(CURRENT_TIMESTAMP AS date)) = 'Wednesday'
THEN DATEADD(DAY, -4, CAST(CURRENT_TIMESTAMP AS date))
WHEN DATENAME(weekday, CAST(CURRENT_TIMESTAMP AS date)) = 'Thursday'
THEN DATEADD(DAY, -5, CAST(CURRENT_TIMESTAMP AS date))
WHEN DATENAME(weekday, CAST(CURRENT_TIMESTAMP AS date)) = 'Friday'
THEN DATEADD(DAY, -6, CAST(CURRENT_TIMESTAMP AS date))
WHEN DATENAME(weekday, CAST(CURRENT_TIMESTAMP AS date)) = 'Saturday'
THEN DATEADD(DAY, -0, CAST(CURRENT_TIMESTAMP AS date))
END) at time zone 'Arab Standard Time' AS start_time,
CONVERT(datetime,
CASE
WHEN datename(weekday,cast(CURRENT_TIMESTAMP AS date)) = 'Sunday' THEN dateadd(day,0,cast(CURRENT_TIMESTAMP AS date))
WHEN datename(weekday,cast(CURRENT_TIMESTAMP AS date)) = 'Monday' THEN dateadd(day,-1,cast(CURRENT_TIMESTAMP AS date))
WHEN datename(weekday,cast(CURRENT_TIMESTAMP AS date)) = 'Tuesday' THEN dateadd(day,-2,cast(CURRENT_TIMESTAMP AS date))
WHEN datename(weekday,cast(CURRENT_TIMESTAMP AS date)) = 'Wednesday' THEN dateadd(day,-3,cast(CURRENT_TIMESTAMP AS date))
WHEN datename(weekday,cast(CURRENT_TIMESTAMP AS date)) = 'Thursday' THEN dateadd(day,-4,cast(CURRENT_TIMESTAMP AS date))
WHEN datename(weekday,cast(CURRENT_TIMESTAMP AS date)) = 'Friday' THEN dateadd(day,-5,cast(CURRENT_TIMESTAMP AS date))
WHEN datename(weekday,cast(CURRENT_TIMESTAMP AS date)) = 'Saturday' THEN dateadd(day,-6,cast(CURRENT_TIMESTAMP AS date))
END) at time zone 'Arab Standard Time' as end_time)
SELECT
USERID,
DEPOSIT,
RMwin,
CASE
WHEN DEPOSIT > 0
AND RMwin <= DEPOSIT
AND RMwin > 0 THEN
RMWIN * 0.3
WHEN RMwin > DEPOSIT
AND DEPOSIT > 0 THEN
DEPOSIT *.3
WHEN RMwin <= 0 THEN
0 ELSE 0
END AS CB,
CASE
WHEN DEPOSIT + RMwin = 0 THEN
0 ELSE 1
END AS check_,
FORMAT ( min_lt, 'dd/MM/yy HH:mm' ) AS min_lt,
format ( min_kuw, 'dd/MM/yy HH:mm' ) AS min_kuw,
format ( max_lt, 'dd/MM/yy HH:mm' ) AS max_lt,
format ( max_kuw, 'dd/MM/yy HH:mm' ) AS max_kuw,
min_id,
max_id
FROM
(
SELECT
UserID,
SUM ( DEPOSIT ) AS DEPOSIT,
SUM ( RMwin ) AS RMwin,
MIN ( AccountTranID ) AS min_id,
MAX ( AccountTranID ) AS max_id,
MIN ( local_time ) AS min_lt,
MIN ( kuwait_date ) AS min_kuw,
MAX ( local_time ) AS max_lt,
MAX ( kuwait_date ) AS max_kuw
FROM
(
SELECT
AccountTranID,
TranType,
UserID,
datetime,
datetime AT TIME ZONE 'Romance Standard Time' AS local_time,
datetime AT TIME ZONE 'Romance Standard Time' AT TIME ZONE 'Arab Standard Time' AS kuwait_date,
CASE
TranType
WHEN 'GAME_B' THEN
- AmountReal
WHEN 'GAME_W' THEN
- AmountReal
WHEN 'REFUND' THEN
- AmountReal ELSE 0
END AS RMwin,
CASE
WHEN TranType = 'DEPOSIT' THEN
AmountReal ELSE 0
END AS DEPOSIT
FROM
admin_all.DataFeed
WHERE
datetime AT TIME ZONE 'Romance Standard Time' AT TIME ZONE 'Arab Standard Time' >= ( Select start_date from DateRange) AT TIME ZONE 'Arab Standard Time' ) `enter code here`
AND datetime AT TIME ZONE 'Romance Standard Time' AT TIME ZONE 'Arab Standard Time' < ( Select end_date from DateRange) AT TIME ZONE 'Arab Standard Time' )
) trans
GROUP BY
答案 2 :(得分:0)
考虑DATEPART
来获取工作日编号,并应用算术来检索相对于当前日期的上一个星期六至最后一个星期日。以下两个表达式可以替换第一个查询的长CASE
语句:
DATEADD(DAY, -1*(DATEPART(DW, CURRENT_TIMESTAMP)),
CAST(CURRENT_TIMESTAMP AS DATE)) AS LAST_SATURDAY
DATEADD(DAY, -1*(DATEPART(DW, CURRENT_TIMESTAMP)-1),
CAST(CURRENT_TIMESTAMP AS DATE)) AS LAST_SUNDAY
从那里轻松集成到大型查询的WHERE
子句:
...
WHERE
datetime AT TIME ZONE 'Romance Standard Time' AT TIME ZONE 'Arab Standard Time' >=
( DATEADD(DAY, -1*(DATEPART(DW, CURRENT_TIMESTAMP)),
CAST(CURRENT_TIMESTAMP AS DATE)) AT TIME ZONE 'Arab Standard Time' )
AND datetime AT TIME ZONE 'Romance Standard Time' AT TIME ZONE 'Arab Standard Time' <
( DATEADD(DAY, -1*(DATEPART(DW, CURRENT_TIMESTAMP)-1),
CAST(CURRENT_TIMESTAMP AS DATE))AT TIME ZONE 'Arab Standard Time' )
...
PHP
在PHP中运行时,请考虑使用parameterization,甚至可以在PHP中计算日期(没有单独的仅返回常量的SQL查询):
$start_date = date('Y-m-d H:i:s', strtotime("last Saturday"));
$end_date = date('Y-m-d H:i:s', strtotime("last Sunday"));
$sql = "...
WHERE
datetime AT TIME ZONE 'Romance Standard Time' AT TIME ZONE 'Arab Standard Time' >= ?
AND datetime AT TIME ZONE 'Romance Standard Time' AT TIME ZONE 'Arab Standard Time' < ?
..."
$params = array($start_date , $end_date);
# sqlsrv API
$stmt = sqlsrv_query($conn, $sql, $params);
# odbc API
$stmt = odbc_prepare($conn, $sql);
$success = odbc_execute($stmt, $params);