2010-07-27 2 views
2

J'ai une table CE SQL Server 3.5 (Transactions) avec le schéma suivant:Aidez-moi avec cette requête SQL

  • ID
  • TRANSACTION_DATE
  • Catégorie
  • Description de
  • Quantité

Q uery:

SELECT Transaction_Date, SUM(Amount) 
    FROM Transactions 
GROUP BY Transaction_Date; 

Je suis en train de faire un SUM (montant) et le groupe par transaction_date juste que je peux obtenir le montant total pour chaque jour, mais je veux revenir les valeurs même pendant des jours il n'y a eu aucune opération si Fondamentalement, le record pour une journée sans transactions aurait juste 0,00 $ pour le montant.

Merci pour l'aide!

+0

Est-ce que SQL Server CE prend en charge 'master.dbo.spt_values'? –

Répondre

0

Vous avez besoin d'un tableau Calendrier pour sélectionner les dates. Sinon, si vous avez une table Numbers, vous pouvez le transformer efficacement en une table Calendar. Fondamentalement, c'est juste une table avec chaque date dedans. Il est assez facile de construire et de générer les données pour cela et il est très pratique pour ces situations. Ensuite, vous utilisez simplement:

SELECT 
    C.calendar_date, 
    SUM(T.amount) 
FROM 
    Calendar C 
LEFT OUTER JOIN Transactions T ON 
    T.transaction_date = C.calendar_date 
GROUP BY 
    C.calendar_date 
ORDER BY 
    C.calendar_date 

Quelques choses à garder à l'esprit:

Si vous envoyez à un bout avant ou moteur de reporting, vous devez simplement envoyer les dates que vous avez (votre requête d'origine) et faire en sorte que la partie frontale remplisse elle-même les 0,00 $ par jour si c'est possible.

Aussi, j'ai supposé ici que la date est une valeur de date exacte sans composant de temps (d'où le "=" dans la jointure). Votre table de calendrier peut inclure un "start_time" et "end_time" de sorte que vous pouvez utiliser BETWEEN pour travailler avec des dates qui incluent une partie de temps. Cela vous évite d'avoir à supprimer des portions de temps et potentiellement ruiner l'utilisation de l'index. Vous pouvez également calculer les points de début et de fin de la journée lorsque vous l'utilisez, mais puisqu'il s'agit d'une table de travail préremplie, il est plus facile pour l'OMI d'inclure start_time et end_time.

-1

Si vous voulez des dates qui ne sont pas les transactions à apparaître , vous pouvez ajouter une transaction DUMMY pour chaque jour avec la quantité de zéro il ne sera pas interférer avec SUM et que si ce que vous voulez

+0

Je suggérerais fortement contre cela. Une fois que vous commencez à mettre des déchets dans votre base de données, vous finirez par en sortir. Il y a toujours des conséquences involontaires à ce genre de «kludge». –

0

Non que si tout cela fonctionne avec cE

avec table commune expressions

DECLARE @StartDate DATETIME 
DECLARE @EndDate DATETIME 

SET @StartDate = '2010-07-10' 
SET @EndDate = '2010-07-20' 

;WITH Dates AS (
    SELECT @StartDate AS DateValue 
    UNION ALL 
    SELECT DateValue + 1 
    FROM Dates 
    WHERE DateValue + 1 <= @EndDate 
) 
SELECT  Dates.DateValue, ISNULL(SUM(Transactions.Amount), 0) 
FROM  Dates 
LEFT JOIN Transactions ON 
       Dates.DateValue = Transactions.Transaction_Date 
GROUP BY Dates.DateValue; 

avec boucle + table temporaire

DECLARE @StartDate DATETIME 
DECLARE @EndDate DATETIME 

SET @StartDate = '2010-07-10' 
SET @EndDate = '2010-07-20' 

SELECT @StartDate AS DateValue INTO #Dates 

WHILE @StartDate <= @EndDate 
BEGIN 
    SET @StartDate = @StartDate + 1 
    INSERT INTO #Dates VALUES (@StartDate) 
END 

SELECT  Dates.DateValue, ISNULL(SUM(Transactions.Amount), 0) 
FROM  #Dates AS Dates 
LEFT JOIN Transactions ON 
       Dates.DateValue = Transactions.Transaction_Date 
GROUP BY Dates.DateValue; 

DROP TABLE #Dates 
0

Vous aurez besoin d'une limite supérieure et inférieure pour votre déclaration, mais peut-être que cela vous aidera.

DECLARE @Start smalldatetime, @End smalldatetime 

SELECT @Start = 'Jan 1 2010', @End = 'Jan 18 2010'; 

--- make a CTE of range of dates we're interested in 
WITH Cal AS (
    SELECT CalDate = convert(datetime, @Start) 
    UNION ALL 
    SELECT CalDate = dateadd(d,1,convert(datetime, CalDate)) FROM Cal WHERE CalDate < @End 

) 

SELECT CalDate AS TransactionDate, ISNULL(SUM(Amount),0) AS TransactionAmount 
FROM Cal AS C 
LEFT JOIN Transactions AS T On C.CalDate = T.Transaction_Date 
GROUP BY CalDate ; 
+0

Je ne pense pas que les CTE sont disponibles dans SQL Server CE. –

0

Une fois que vous avez une table de calendrier (plus tard), vous pouvez alors faire une jointure interne sur la plage de vos données pour remplir les dates manquantes:

SELECT CalendarDate, NULLIF(SUM(t.Amount),0) 
FROM (SELECT CalendardDate FROM Calendar 
WHERE CalendarDate>= (SELECT MIN(TransactionDate) FROM Transactions) AND 
    CalendarDate<= (SELECT MAX(TransactionDate) FROM Transactions)) c 
LEFT JOIN 
    Transactions t ON t.TransactionDate=c.CalendarDate 
GROUP BY CalendarDate 

Pour créer une table de calendrier , vous pouvez utiliser un CTE:

WITH CalendarTable 
AS 
(
    SELECT CAST('20090601' as datetime) AS [date] 
    UNION ALL 
    SELECT DATEADD(dd, 1, [date]) 
    FROM CTE_DatesTable 
    WHERE DATEADD(dd, 1, [date]) <= '20090630' /* last date */ 
) 
SELECT [date] FROM CTE_DatesTable 
OPTION (MAXRECURSION 0); 

en combinant les deux, nous avons

WITH CalendarTable 
AS 
(
    SELECT MIN(TransactionDate) FROM Transactions AS [date] 
    UNION ALL 
    SELECT DATEADD(dd, 1, [date]) 
    FROM CTE_DatesTable 
    WHERE DATEADD(dd, 1, [date]) <= (SELECT MAX(TransactionDate) FROM Transactions) 
) 
SELECT c.[date], NULLIF(SUM(t.Amount),0) 
FROM Calendar c 
LEFT JOIN 
    Transactions t ON t.TransactionDate=c.[date] 
GROUP BY c.[date]