การรวม DateDiff และเอาต์พุตเรียงซ้อนสำหรับแต่ละแถวในตัวแปร (SQL-Server) (PHP)

มันจะยากมากที่จะอธิบายสิ่งนี้ด้วยคำพูด ดังนั้นฉันจะพยายามยกตัวอย่างเล็กๆ น้อยๆ เพื่ออธิบายให้คุณทราบว่าฉันต้องการอะไร:

ตัวอย่างเช่นฉันมีตาราง SQL-Server นี้

+-------+-------+------+
| TestID| Start | End  | 
+-------+-------+------+
|     1 | DateA | DateB|  
|     2 | DateA | DateB| 
|     3 | DateA | DateB|   
|     4 | DateA |      |     
+-------+-------+------+

สิ่งที่ฉันต้องการคือตารางนี้:

$ส่วนที่เหลือ = 1,000

+-------+-------+------+----------+-----------+----------+
| TestID| Start | End  | Testtime | Totaltime | Resttime |
+-------+-------+------+----------+-----------|----------|
|     1 | DateA | DateB|   214    |   214     |   786    |
|     2 | DateA | DateB|   100    |   314     |   686    |
|     3 | DateA | DateB|   200    |   514     |   486    |
|     4 | DateA |      |          |           |          |
+-------+-------+------+----------+-----------+----------+

ฉันมีปัญหาในการทำความเข้าใจสิ่งที่ฉันต้องรวมเข้าด้วยกัน

นี่คือรหัสเพื่อรับตาราง SQL-Server แรก

SELECT  TestID, Start, End, DATEDIFF(hour, Start, End) AS Testtime
                         FROM Testresults
                         WHERE TesttableID = 1

แต่ละแถวมี TesttableID = 1 ขอบคุณสำหรับความช่วยเหลือ

แก้ไข: เวอร์ชันเซิร์ฟเวอร์ SQL: 9.0.5057

แก้ไข : ฉันได้รับผลลัพธ์แต่ผลลัพธ์ไม่ถูกต้อง สลับเป็น Totaltime และ Resttime

SELECT t1.TestID,
       t1.start,
       t1.end, 
       t1.TesttableID,
       DATEDIFF(hour,t1.start,t1.end) as Testtime,
       (SELECT SUM(DATEDIFF(hour,t2.start,t2.end))
        FROM Testresults t2
       WHERE t2.TestID <= t1.TestsID AND t2.TesttableID = 1  ) AS Totaltime,
       (SELECT 1000-SUM(DATEDIFF(hour,t2.start,t2.end))
       FROM Testresults t2
       WHERE t2.TestID <= t1.TestIDAND t2.TesttableID = 1  ) AS Resttime  FROM Testresults t1 WHERE t1.TesttableID = 1

สิ่งที่ฉันได้รับคือผลลัพธ์เหล่านี้ พวกเขาเปลี่ยน..:

+-------+-------+------+----------+-----------+----------+
| TestID| Start | End  | Testtime | Totaltime | Resttime |
+-------+-------+------+----------+-----------|----------|
|     1 | DateA | DateB|   214    |   514     |   486    |
|     2 | DateA | DateB|   100    |   300     |   700    |
|     3 | DateA | DateB|   200    |   200     |   800    |
|     4 | DateA |      |          |           |          |
+-------+-------+------+----------+-----------+----------+

person Daniel    schedule 17.01.2019    source แหล่งที่มา
comment
ข้อมูลทั้งหมดที่โพสต์นี้: stackoverflow .com/questions/860966/   -  person Sanpas    schedule 17.01.2019
comment
ปัญหาที่แท้จริงที่นี่คือการใช้ SQL Server เวอร์ชันอายุ 14 ปีซึ่งไม่ได้รับการสนับสนุนเป็นเวลา 4 ปี ถึงเวลาอัพเกรดแล้ว   -  person Larnu    schedule 17.01.2019


คำตอบ (3)


คุณสามารถลองสิ่งนี้:

SELECT TestId,
       Start,
       End,
       Testtime,
       SUM(Testtime) OVER (ORDER BY TestId ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW),
       1000 - SUM(Testtime) OVER (ORDER BY TestId ROWS BETWEEN AND UNBOUNDED PRECEDING AND CURRENT ROW)
FROM MyTable

สำหรับ SQL Server 2005 คุณสามารถใช้ JOIN เพื่อทำสิ่งนี้ให้สำเร็จ:

select t1.testid,
       t1.start, 
       t1.end, 
       DATEDIFF(hour, t1.Start, t1.End), 
       sum(DATEDIFF(hour, t2.Start, t2.End)), 
       1000 - sum(DATEDIFF(hour, t2.Start, t2.End))
from MyTable t1
join MyTable t2 on t1.testid >= t2.testid
group by t1.testid, t1.start, t1.end, t1.Start, t1.End
person Michał Turczyn    schedule 17.01.2019
comment
เวอร์ชันคือ: 9.0.5057 - person Daniel; 17.01.2019
comment
กว่าที่ฉันเดาว่าฉันต้องจัดการมันด้วย php ด้วยฟังก์ชัน - person Daniel; 17.01.2019
comment
testtime เป็นเพียงชื่อชั่วคราว และฉันไม่มี table2 ฉันต้องการ Totaltime และ Resttime เป็นชื่อชั่วคราว ฉันลองสิ่งนี้: SELECT TestID, start, end, DATEDIFF(hour,start,end) AS Testtime, (SELECT SUM(Testtime) FROM Testresults WHERE TestID ‹=aa.TestID) AS Totaltime FROM Testresult as aa ORDER BY Testtime, Totaltime But ฉันได้รับข้อผิดพลาด: เวลาทดสอบชื่อคอลัมน์ไม่ถูกต้อง - person Daniel; 17.01.2019
comment
ตารางแรกมีการเปลี่ยนแปลง - person Daniel; 17.01.2019
comment
ยังคงชื่อคอลัมน์ Testtime ไม่ถูกต้อง เนื่องจากคอลัมน์นี้ไม่มีอยู่เพียงชั่วคราวเท่านั้น - person Daniel; 17.01.2019
comment
ไม่รู้จริง SELECT t1.TestID, t1.start, t1.end, DATEDIFF (ชั่วโมง, เริ่มต้น, สิ้นสุด) AS Testtime, t1.Testtime, SUM (t2.Testtime), 1,000-SUM (t2.Testime) จากผลการทดสอบ t1 JOIN Testresults บน t1.TestID >= t2.TestID GROUP BY t1.TestID, t1.start, t1.end, t1.Testtime ชื่อคอลัมน์ไม่ถูกต้อง เวลาทดสอบและชื่อคอลัมน์หลายคอลัมน์ - person Daniel; 17.01.2019
comment
ปัญหาเดียวกันในรหัสของคุณคือไวยากรณ์คอลัมน์นามแฝงหายไป เวลาทดสอบและเวลาที่เหลือที่ไม่รู้จัก - person Daniel; 17.01.2019
comment
ตอนนี้ฉันได้รับคำตอบแล้ว แต่ไม่ใช่สิ่งที่ฉันคาดหวัง ฉันแก้ไขโพสต์แรกของฉันด้วยรหัสจริง คุณสามารถตรวจสอบมันได้ไหม ขอบคุณ - person Daniel; 17.01.2019

จากข้อมูล ตัวอย่าง ที่เราได้รับ ผลลัพธ์ที่ได้คือ:

DECLARE @Rest int = 1000;

WITH VTE AS (
    SELECT *
    FROM (VALUES(1,'DateA','DateB',214),
                (2,'DateA','DateB',100),
                (3,'DateA','DateB',200),
                (4,'DateA',NULL,NULL)) V(TestID,[Start],[End],Testtime))
SELECT VTE.TestID,
       VTE.Start,
       VTE.[End],
       VTE.Testtime,
       CASE WHEN [End] IS NOT NULL THEN SUM(VTE.Testtime) OVER (ORDER BY VTE.TestID ASC
                                                                ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) END AS TotalTime,
       CASE WHEN [End] IS NOT NULL THEN @Rest - SUM(VTE.Testtime) OVER (ORDER BY VTE.TestID ASC
                                                                        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) END AS RestTime
FROM VTE;

โปรดทราบว่าคุณอาจต้องใช้ PARTITION BY บางประเภทในส่วนคำสั่ง OVER แต่ฉันไม่รู้ว่าจะต้องใช้อะไรบ้างโดยพิจารณาจากข้อมูลที่จำกัดที่เรามี

person Larnu    schedule 17.01.2019
comment
เวอร์ชัน SQL ของฉันไม่รองรับ Over() - person Daniel; 17.01.2019
comment
OVER เปิดตัวใน SQL Server 2005 (iirc), @Daniel คุณ จริงๆ ใช้บางอย่างก่อนหน้านั้นหรือไม่? ROWS BETWEEN เปิดตัวพร้อมกับ SQL Server 2012 อย่างไรก็ตาม 2008 เหลือการสนับสนุนเพิ่มเติมอีกเพียงไม่กี่เดือนเท่านั้น และ 2005 ก็หมดการสนับสนุนแล้ว ดังนั้นคุณควรอัปเกรดจริงๆ เสียก่อน ทำไมคุณไม่ได้? - person Larnu; 17.01.2019
comment
เวอร์ชัน: 9.0.5057 - person Daniel; 17.01.2019

คุณสามารถลองสิ่งนี้:

 CREATE TABLE #MyTable  
    (PrimaryKey   int PRIMARY KEY,  
       DateValueBegin      DATETIME,
       DateValueEnd      DATETIME,
       NbValue      int
      );  
    GO  

    INSERT INTO #MyTable 
    SELECT 1, DATEADD(HOUR,-2,GETDATE()), GETDATE(), 214
    UNION
    SELECT 2, DATEADD(HOUR,-2,GETDATE()), DATEADD(HOUR,-1,GETDATE()), 100
    UNION 
    SELECT 3, DATEADD(HOUR,-2,GETDATE()), GETDATE(), 200
    UNION
    SELECT 4, DATEADD(HOUR,-1,GETDATE()), NULL, 210
    UNION
    SELECT 5, DATEADD(HOUR,-1,GETDATE()), NULL, 0;

    SELECT *, SUM(NbValue) OVER(ORDER BY PrimaryKey 
         ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as 'Totaltime',
         1000 - SUM(NbValue) OVER(ORDER BY PrimaryKey 
         ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) As 'RestTime'    FROM #MyTable

    DROP TABLE  #MyTable

อธิบายได้ที่โพสต์นี้: คำนวณ Running Total ใน SQL Server

ผลลัพธ์ :

PrimaryKey  DateValueBegin  DateValueEnd    NbValue Totaltime   RestTime
1   2019-01-17 09:48:05.123 2019-01-17 11:48:05.123 214 214 786
2   2019-01-17 09:48:05.123 2019-01-17 10:48:05.123 100 314 686
3   2019-01-17 09:48:05.123 2019-01-17 11:48:05.123 200 514 486
4   2019-01-17 10:48:05.123 NULL    210 724 276
5   2019-01-17 10:48:05.123 NULL    0   724 276

สำหรับผู้ใช้ SQL Server เวอร์ชันก่อนหน้าคุณสามารถตรวจสอบได้ที่โพสต์นี้: http://geekswithblogs.net/Rhames/archive/2008/10/28/calculating-running-totals-in-sql-server-2005---the-optimal.aspx

การแก้ไขสำหรับ SQL เวอร์ชันก่อนหน้า:

CREATE TABLE #MyTable  
    (PrimaryKey   int PRIMARY KEY,  
       DateValueBegin      DATETIME,
       DateValueEnd      DATETIME
      );  
    GO  

    INSERT INTO #MyTable 
    SELECT 1, DATEADD(HOUR,-214,GETDATE()), GETDATE()
    UNION
    SELECT 2, DATEADD(HOUR,-100,GETDATE()), DATEADD(HOUR,-1,GETDATE())
    UNION 
    SELECT 3, DATEADD(HOUR,-200,GETDATE()), GETDATE()
    UNION
    SELECT 4, DATEADD(HOUR,-1,GETDATE()), NULL
    UNION
    SELECT 5, DATEADD(HOUR,-1,GETDATE()), NULL;

    SELECT * FROM #MyTable

    SELECT PrimaryKey,
       DateValueBegin,
       DateValueEnd,
       DATEDIFF(hour,DateValueBegin,IIF(DateValueEnd IS NOT NULL ,DateValueEnd, DateValueBegin)) as Testtime,
       (SELECT SUM(DATEDIFF(hour,DateValueBegin,IIF(DateValueEnd IS NOT NULL ,DateValueEnd, DateValueBegin)))
        FROM #MyTable t2
       WHERE t2.PrimaryKey <= t1.PrimaryKey  ) AS Totaltime,
       DATEDIFF(hour,DateValueBegin,IIF(DateValueEnd IS NOT NULL ,DateValueEnd, DateValueBegin)) as Testtime,
       (SELECT 1000-SUM(DATEDIFF(hour,DateValueBegin,IIF(DateValueEnd IS NOT NULL ,DateValueEnd, DateValueBegin)))
        FROM #MyTable t3
       WHERE t3.PrimaryKey <= t1.PrimaryKey  ) AS Resttime
    FROM #MyTable t1



       DROP TABLE  #MyTable

ผลลัพธ์ :

PrimaryKey  DateValueBegin  DateValueEnd    Testtime    Totaltime   Testtime    Resttime
1   2019-01-08 18:17:35.430 2019-01-17 16:17:35.430   214   214 214 786
2   2019-01-13 12:17:35.430 2019-01-17 15:17:35.430   99    313 99  687
3   2019-01-09 08:17:35.430 2019-01-17 16:17:35.430   200   513 200 487
4   2019-01-17 15:17:35.430  NULL                     0 513 0   487
5   2019-01-17 15:17:35.430  NULL                     0 513 0   487

ขออภัย แต่ฉันไม่ทราบการกำหนดค่าทั้งหมดของคุณ คุณลองสิ่งนี้ได้ไหม:

SELECT t1.TestID,
           t1.start,
           t1.end, 
           t1.TesttableID,
           DATEDIFF(hour,t1.start,t1.end) as Testtime,
           (SELECT SUM(DATEDIFF(hour,t2.start,t2.end))
            FROM Testresults t2
           WHERE t2.TestID <= t1.TestsID AND t2.TesttableID = 1  ) AS Totaltime,
           (SELECT 1000-SUM(DATEDIFF(hour,t2.start,t2.end))
           FROM Testresults t2
           WHERE t2.TestID <= t1.TestID AND t2.TesttableID = 1  ) AS Resttime  FROM Testresults t1 WHERE t1.TesttableID = 1
person Sanpas    schedule 17.01.2019
comment
เวอร์ชัน SQL ของฉันไม่รองรับ Over() - person Daniel; 17.01.2019
comment
@Daniel คุณสามารถตรวจสอบได้ที่ลิงค์นี้: ฉันรู้ว่ามีวิธีต่างๆ ในการทำเช่นนี้ใน SQL Server 2000/2005/2008 geekswithblogs.net/Rhames/archive/2008/10/28/ - person Sanpas; 17.01.2019
comment
ฉันทำแล้ว ฉันโพสต์การอัปเดตในโพสต์แรกของฉัน ปัญหาคือตอนนี้ผลลัพธ์ถูกเปลี่ยนแล้ว คุณช่วยตรวจสอบได้ไหม - person Daniel; 17.01.2019
comment
@Daniel เธออัปเดตตัวอย่างของฉันและใช้แบบสอบถามของคุณ :) แจ้งให้ฉันทราบว่ามันเป็นวิธีที่ดีและมีข้อยกเว้นเอาต์พุตของคุณหรือไม่ - person Sanpas; 17.01.2019
comment
ฉันได้รับข้อผิดพลาด: ไวยากรณ์ไม่ถูกต้องใกล้กับ 'IS' คำสั่ง IIF นั้นมีอยู่ใน MDX เท่านั้น - ภาษาคิวรีสำหรับ SQL Server Analysis Services - ฝั่งคลังข้อมูลของ SQL Server T-SQL ธรรมดาไม่มีแหล่งที่มาของคำสั่ง IIF: stackoverflow.com/questions/4374907/ - person Daniel; 17.01.2019
comment
@Daniel ฉันมีการอัปเดตแล้ว ขออภัย แต่ฉันไม่ได้ติดตั้งให้เสร็จสมบูรณ์ ... แจ้งให้เราทราบหากเป็นการสืบค้น บันทึก. เพิ่งเปลี่ยน t2.TestID ›= t1.TestID โดย t2.TestID ‹= t1.TestID - person Sanpas; 17.01.2019
comment
ไม่ นั่นเป็นเพียงการสรุปจาก TestID ทุก Testtimes จนถึงตัวเลขที่สูงเป็น Totaltime My Table เป็นเพียงตัวอย่างเท่านั้นที่มีรายการมากกว่านั้นมาก ฉันลองแล้วเหมือนในโพสต์ที่กล่าวถึงเพื่อแทนที่ te IIF ด้วย Case When, That, Else, End แต่ฉันได้รับข้อผิดพลาด วิธีแก้ไขคือฉันต้องเลือกแถวล่วงหน้าด้วย TesttableID = 1 และรวมเข้าด้วยกัน ดูโพสต์ 1 แต่รหัสหนึ่งที่ฉันต้องการคือถ้า Testend เป็นโมฆะอย่าส่งออกเวลาทั้งหมดและเวลาพักเนื่องจากการทดสอบนี้เปิดอยู่และยังคงดำเนินต่อไป - person Daniel; 18.01.2019