How to remove duplicates in CTE from VARIABLES and TEMPORARY TABLE - sql

I was looking for this solution in internet and none of them worked properly.
I decided to create variables, then accommodates it in the user defined function:
CREATE FUNCTION Top10CustomerByCategoryInYear
(
#Category varchar(MAX),
#StartYear int,
#EndYear int
)
RETURNS #CustomerTop10TableByCategoryInYears TABLE
(
[Customer Name] VARCHAR(MAX),
[Category] VARCHAR(MAX),
Sales int,
Year int
)
AS
BEGIN
INSERT INTO #CustomerTop10TableByCategoryInYears
SELECT
DISTINCT TOP 10 WITH TIES
[Customer Name],
[Category],
SUM(Sales) OVER (PARTITION BY [Customer Name]) as Sales,
YearOfOrderDate as [Year]
FROM [Project4].[dbo].[SuperStore]
WHERE [Category] = #Category AND YearOfOrderDate BETWEEN #StartYear AND #EndYear
ORDER BY Sales DESC
RETURN;
END
GO
It works properly, because for example I am able to return the top 10 Customer in the Furniture Category in 2011 and 2012
SELECT *
FROM Top10CustomerByCategoryInYear('Furniture',2011,2011)
SELECT *
FROM Top10CustomerByCategoryInYear('Furniture',2012,2012)
Then, I would like to have all records (2011-2014) in one Table. I decided to use CTE, then JOIN these Tables by Category:
WITH Furniture2011 AS (
SELECT DISTINCT *
FROM Top10CustomerByCategoryInYear('Furniture',2011,2011)
), Furniture2012 AS (
SELECT DISTINCT *
FROM Top10CustomerByCategoryInYear('Furniture',2012,2012)
), Furniture2013 AS (
SELECT DISTINCT *
FROM Top10CustomerByCategoryInYear('Furniture',2013,2013)
), Furniture2014 AS (
SELECT DISTINCT *
FROM Top10CustomerByCategoryInYear('Furniture',2014,2014)
)
SELECT DISTINCT *
FROM Furniture2011 F1
JOIN Furniture2012 F2
ON F1.Category = F2.Category
JOIN Furniture2013 F3
ON F1.Category = F3.Category
JOIN Furniture2014 F4
ON F1.Category = F4.Category
Unfortunately there are a lot of duplicates:
[
I tried a lot of solutions from my mind and internet and unfortunately these did not work.
I was wondering if it is possible to combine these Tables using UDF/Variables, TEMP TABLE and finally CTE.
Could you please tell me if it is possible?
If so, would you be so kind as to support me in modifying my codes in SQL to have the desired result without any duplicates?
I would appreciate it if you could advise me on it.

You can have an inline Table function taking a start and end year. Inline is faster than multi-statement.
Start with a virtual table of years, then CROSS APPLY the top 10 results for each year.
CREATE FUNCTION Top10CustomerByCategoryInYear
(
#Category varchar(MAX),
#StartYear int,
#EndYear int
)
RETURNS TABLE
AS RETURN
WITH L0 AS (
SELECT #StartYear - 1 + ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS Year
FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),
(1),(1),(1),(1),(1),(1),(1),(1),
(1),(1),(1),(1),(1),(1),(1),(1),
(1),(1),(1),(1),(1),(1),(1),(1)) AS D(c)
),
Years AS (
SELECT * FROM L0 WHERE Year <= #EndYear
)
SELECT
s.[Customer Name],
#Category AS [Category],
s.Sales,
y.Year
FROM Years y
CROSS APPLY (
SELECT TOP 10 WITH TIES
[Customer Name],
SUM(Sales) AS Sales
FROM [dbo].[SuperStore] s
WHERE [Category] = #Category
AND y.Year = s.YearOfOrderDate
GROUP BY [Customer Name]
ORDER BY Sales DESC
) s;
GO

Related

Incorrect Syntax near With

No matter where I place my With statement inside the SQL query, the keyword in the next line always shows an error, 'Incorrect syntax near keyword'. I also tried putting semi-colon.
; WITH Commercial_subset AS
(
SELECT DISTINCT
PRDID_Clean, Value, [Year]
FROM
Reporting_db_SPKPI.DBO.[tbl_RCCP_commercial]
WHERE
MEASURE = 'Unit Growth Rate'
)
--error appears at truncate
TRUNCATE TABLE Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_dup]
Example 1:
[Example 1][1]
Example 2:
[Example 2][2]
What am I missing?
[1]: https://i.stack.imgur.com/lkfVd.png
[2]: https://i.stack.imgur.com/tZRnG.png
My Final code after getting suggestions in the comments,
--Ensure the correct database is selected for creating the views
USE Reporting_db_SPKPI
--Create the table where new values will be appended
Insert into Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_dup]
Select *, Replace(productID,'-','') as ProductID_clean from Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR]
GO
--Create a subset as view which will be used for join later
Create or Alter View QRY_Commerical_Subset AS
Select Distinct PRDID_Clean, Value, [Year] From Reporting_db_SPKPI.DBO.[tbl_RCCP_commercial] where MEASURE = 'Unit Growth Rate'
Go
--Create a view with distinct list of all SKUs
CREATE OR ALTER VIEW QRY_RCCP_TEMP AS
SELECT
PRODUCTID, ROW_NUMBER() Over (ORDER BY ProductID) AS ID
FROM (
SELECT
DISTINCT A.ProductID_clean ProductID
FROM
Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_dup] A
LEFT JOIN
Reporting_db_SPKPI.DBO.QRY_Commerical_Subset B ON A.ProductID_clean = B.PRDID_Clean
WHERE
B.PRDID_Clean IS NOT NULL --and A.filename = 'Capacity Planning_INS_Springhill' --DYNAMIC VARIABLE HERE
and Cast(A.SnapshotDate as date) =
(SELECT Max(Cast(SnapshotDate as date)) FROM reporting_db_spkpi.dbo.tbl_RCCP_3_NR)
) T
GO
SET NOCOUNT ON
-- For every product id from the distinct list iterate the following the code
DECLARE #I INT = 1
WHILE #I <= (SELECT MAX(ID) FROM QRY_RCCP_TEMP)
BEGIN
DECLARE #PRODUCT NVARCHAR(50) = (SELECT PRODUCTID FROM QRY_RCCP_TEMP WHERE ID = #I)
DROP TABLE Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_temp]
--Retrieve last 12 months of value from NR and add it to a temp table in increasing order of their months. These 12 data points will be baseline
SELECT
Top 12 A.*,
Case When B.[Value] is Null then 0 else CAST(B.[Value] as float) End GROWTH
INTO
Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_temp]
FROM
Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_dup] A
LEFT JOIN
--using the view here
QRY_Commerical_Subset B ON B.PRDID_Clean = A.ProductID_clean AND B.[YEAR] = YEAR(A.[MONTH])+1
WHERE
A.PRODUCTID= #PRODUCT
AND Cast(A.SnapshotDate AS DATE) = (SELECT Max(Cast(SnapshotDate AS DATE)) FROM reporting_db_spkpi.dbo.[tbl_RCCP_3_NR_dup])
Order by
[Month] desc
-- Generate 3 years of data
DECLARE #J INT = 1
WHILE #J<=3
BEGIN
--Calculate next year's value
UPDATE Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_temp]
SET
[Value] = [Value]*(1+ GROWTH),
[MONTH] = DATEADD(YEAR,1,[Month]),
MonthCode= 'F' + CAST(CAST(SUBSTRING(MonthCode,2,LEN(MonthCode)) AS INT) + 12 AS NVARCHAR(10))
--Add it to the NR table.
Insert into Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_dup]
(ProductID, MonthCode, Value, Month, FileName,
LastModifiedDate, SnapshotDate, Quarter, IsError, ErrorDescription)
Select
ProductID, MonthCode, Value, Month, FileName,
LastModifiedDate, SnapshotDate, Quarter, IsError, ErrorDescription
from
Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_temp]
--Update growth rate for next year
UPDATE Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_temp]
SET GROWTH = Case When B.[Value] is Null then 0 else CAST(B.[Value] as float) End
FROM Reporting_db_SPKPI.DBO.QRY_Commerical_Subset B
WHERE B.PRDID_Clean = ProductID_clean AND [YEAR] = YEAR([MONTH])+1
SET #J=#J+1
END
SET #I=#I+1
END
DROP VIEW QRY_RCCP_TEMP
DROP VIEW QRY_Commerical_Subset
The WITH is a Common Table Expression, aka CTE.
And a CTE is like a template for a sub-query.
For example this join of the same sub-query:
SELECT *
FROM (
select distinct bar
from table1
where foo = 'baz'
) AS foo1
JOIN (
select distinct bar
from table1
where foo = 'baz'
) AS foo2
ON foo1.bar > foo2.bar
Can be written as
WITH CTE_FOO AS (
select distinct bar
from table1
where foo = 'baz'
)
SELECT *
FROM CTE_FOO AS foo1
JOIN CTE_FOO AS foo2
ON foo1.bar > foo2.bar
It's meant to be used with a SELECT.
Not with a TRUNCATE TABLE or DROP TABLE.
(It can be used with an UPDATE though)
As such, treat the TRUNCATE as a seperate statement.
TRUNCATE TABLE Reporting_db_SPKPI.DBO.[tbl_RCCP_3_NR_dup];
WITH Commercial_subset AS
(
SELECT DISTINCT
PRDID_Clean, Value, [Year]
FROM
Reporting_db_SPKPI.DBO.[tbl_RCCP_commercial]
WHERE
MEASURE = 'Unit Growth Rate'
)
SELECT *
FROM Commercial_subset;
Btw, the reason why many write a CTE with a leading ; is because the WITH clause raises an error if the previous statement wasn't ended with a ;. It's just a small trick to avoid that error.

Multilevel CTE Expression slows the execution (Reposted with changes) [duplicate]

This question already exists:
Multilevel CTE Expression slows the execution [closed]
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Duplicate This question has been answered, is not unique, and doesn’t differentiate itself from another question.
In SQL Server, I have a table-valued function which contains a multi-level CTE as shown in the code here:
CREATE FUNCTION [dbo].[GetDataset_Test]
(#XMLBlock XML, #Id INT)
RETURNS
#tempTable TABLE
(
methodID INT,
[Id] INT,
SavingMessage varchar(50)
)
AS
BEGIN
DECLARE #ObjectID INT = 2;
DECLARE #ExchangeRate INT = 2;
DECLARE #Cond INT = 1;
DECLARE #Param1 varchar(50) = 'name1';
DECLARE #Param2 varchar(50) = 'name2';
WITH CTE AS
(
SELECT
Col1,
con,
DiscountLine,
tempNumber,
ItemCostExVAT,
Quantity,
SomeValue,
methodID,
VATAmount,
SubTypeID,
Line,
VATMultiplier,
ROUND(dbo.GetAmountCustomFunction(COALESCE(Id, AnotherId), COALESCE(Price, PriceValue)), 2) As [Amount]
FROM
dbo.GetObject(#Id, #ObjectID, #ParameterBlock) AS BC
INNER JOIN
dbo.fnPrices(#ID, #CurrencyID) BPD ON BPD.Id = BC.productid
),
CTE1 AS
(
SELECT
*,
CASE WHEN con = 0 THEN Quantity ELSE 1 END AS Quantity
FROM
CTE
WHERE
1 = SomeValue
),
CTE2 AS
(
Select *,
MIN(CASE WHEN DiscountLine=1 THEN 1 ELSE 20 END) over (PARTITION by tempNumber) As StockControlled,
SUM(ItemCostExVAT * Quantity) OVER ( PARTITION BY tempNumber ) AS tempCost ,
ROUND(CASE
WHEN methodID = 8 THEN DiscValue
WHEN methodID = 2 THEN END ,
DicsValue,VATAmount),2) AS AmountExVAT
From CTE1
),
CTE3
(
SELECT
*,
ROUND(CASE
WHEN SubTypeID = 1 AND Line = 1 THEN -1 * AmountExVAT
ELSE 20
END, 2) PriceExVAT
FROM
CTE2
),
CTE4
(
SELECT
*,
ROUND(#ExchangeRate * CASE WHEN #Cond = 1 THEN AmountExVAT * VATMultiplier ELSE 20 END, 2) CashBack
FROM
CTE3
),
CTE5
(
SELECT
*,
dbo.FormatMessage(#Param1, #Param2) AS SavingMessage
FROM
CTE4
)
INSERT INTO #tempTable
SELECT
methodID, [Id], SavingMessage
FROM
CTE5
RETURN
END
In above query because of multi-level CTE and table value parameter I can think that its trying to query recursively and taking more execution time.
I know that we cannot use temporary table as function parameter, is there any alternative of this or can I use temporary table by any way in function?
Or can I make some changes in CTE to improve my T-SQL function query execution time?

Returning the following season and year

For a particular season and year when it started I have to get the following season and year when it starts, e.g. for Summer 2021 I should get Autumn 2021, and for Winter 2021 I should get Spring 2022.
"Seasons" table has the "Order" column which indicates the order of seasons in a year, so it looks like this:
SeasonID
Order
Name
1
1
Spring
2
2
Summer
3
3
Autumn
4
4
Winter
Remark: "Order" column may seem redundant, but this is actually simplified/adapted version of the problem I have, where "Order" column is neccesary.
I have a stored procedure that has #Year and #SeasonID as input parameters. I have to get following season/year in #FollowingSeasonID and #FollowingYear parameters, which I use later in the stored procedure. I'm not sure if I've used the best technique for that:
(...)
DECLARE #FollowingSeasonID int;
DECLARE #FollowingYear int;
if object_id('tempdb..#Years') is not null drop table #Years
CREATE TABLE #Years ([Year] int)
INSERT INTO #Years ([Year]) VALUES (#Year), (#Year + 1)
SELECT #FollowingSeasonID = FollowingSeasonID, #FollowingYear = FollowingYear
FROM
(SELECT SeasonID,
[Year],
LEAD(SeasonID) OVER (ORDER BY [Year], Order) AS FollowingSeasonID,
LEAD([Year]) OVER (ORDER BY [Year], Order) AS FollowingYear
FROM Seasons
CROSS JOIN #Years) t
WHERE SeasonID = #SeasonID AND [Year] = #Year
(...)
Is there a better way to do that? Could it be achieved in just one query?
I need those values in multiple stored procedures/views/... so I wanted to extract that part of code if a function. Scalar valued function can't return two values, so I have to create a table valued function (and I have to use table variable instead of temp table #Years). However, is there a better way to do that instead of having a table valued function that always returns just one row?
You can wrap this code in UDF and you should be able to get seasonId, year
DECLARE #season table(SeasonId int, SeasonOrder int, Name varchar(10))
INSERT INTo #season values
(1, 1 ,'Spring')
,(2, 2 ,'Summer')
,(3, 3 ,'Autumn')
,(4, 4 ,'Winter');
DECLARE #FollowingSeasonID int;
DECLARE #FollowingYear int;
DECLARE #year int = 2021, #SeasonId int = 2;
;WITH CTE_YearSeason AS
(
SELECT y,s.* FROM #season as s
CROSS APPLY
(VALUES (#year), (#year+1)
) as t(y)
), cte_ranking as
(
SELECT *, row_number() over (order by y,SeasonOrder) as rnk
FROM CTE_YearSeason)
SELECT SeasonId, Y as year
FROM cte_ranking as c
where c.rnk = (SELECT c1.rnk
from cte_ranking as c1
where c1.SeasonId = #SeasonId and c1.y = #year) +1
SeasonId
year
3
2021
Unless I've misunderstood, given a single seasonId you just need the following Id and reset it to 1 and increment the year if necessary?
declare #seasonid int=1, #Year int=2021
select FollowingSeasonID, #Year + yr FollowingYear
from (
select *,
IsNull(Lead(SeasonId) over(order by [order]),1) FollowingSeasonID,
case when Lead(SeasonId) over(order by [order]) is null then 1 else 0 end yr
from seasons
)s
where SeasonId=#SeasonId
If you don't want to use a TVF you could just use this as a view/cte, joining on currentId and return the followingId and yr value to add to your current year.

SSRS Recursive Sum

I have created a tablet report in vs2017 see here. Each balanceindicator has a parent key. For my "Sum at the end of last year" field i have configure a recursive sum by parentKey for BalanceIndicatorKey group. At this point all is good and works perfectly. Now i have added a column group by organizationKey. What i need is to get the recursive sum for each organization considering the Organization and balance indicator My report
Here is the stored procedure that i use for my report
LTER PROCEDURE [dbo].[GetFactBalance]
#organizationKey int,
#year int,
#month int
AS
BEGIN
SET NOCOUNT ON;
;with cte_Orgs
as
(
select OrganizationKey,
[Description]
from DimOrganization o
where o.OrganizationKey = #organizationKey
union all
select o.OrganizationKey,
o.[Description]
from cte_Orgs join
DimOrganization o on o.ParentKey = cte_Orgs.OrganizationKey
),
cte_start as (
select
Sum(fa.SumReg) SumReg,
fa.BalanceIndicatorKey,
cte_Orgs.OrganizationKey,
cte_Orgs.Description
from FactBalance fa join
cte_Orgs on cte_Orgs.OrganizationKey = fa.OrganizationKey
where fa.OrganizationKey = cte_Orgs.OrganizationKey
and [Year] = #year-1 and [Month] = 12
group by
fa.BalanceIndicatorKey,
cte_Orgs.OrganizationKey,
cte_Orgs.Description
),
cte_curr as (
select
Sum(fa.SumReg) SumReg,
fa.BalanceIndicatorKey,
cte_Orgs.OrganizationKey,
cte_Orgs.Description
from FactBalance fa join
cte_Orgs on cte_Orgs.OrganizationKey = fa.OrganizationKey
where [Year] = #year and [Month] = #month
group by
fa.BalanceIndicatorKey,
cte_Orgs.OrganizationKey,
cte_Orgs.Description
),
cte_res as (
select
ISNULL(cte_curr.BalanceIndicatorKey, cte_start.BalanceIndicatorKey) BalanceIndicatorKey,
ISNULL(cte_start.OrganizationKey, cte_curr.OrganizationKey) OrganizationKey,
ISNULL(cte_start.Description, cte_curr.Description) [OrgName],
cte_start.SumReg SumRegStart,
cte_curr.SumReg SumReg
from cte_curr full join cte_start on cte_curr.BalanceIndicatorKey = cte_start.BalanceIndicatorKey
and cte_curr.OrganizationKey = cte_start.OrganizationKey)
select
cte_res.OrganizationKey,
cte_res.OrgName,
bi.BalanceIndicatorKey,
bi.Description [Description],
bi.Code,
bi.ParentKey,
cte_res.SumRegStart,
cte_res.SumReg,
isnull(bi.Level, 0) [Level]
from DimBalanceIndicator bi
full join cte_res on cte_res.BalanceIndicatorKey = bi.BalanceIndicatorKey
END
Any ideas? Thank you

Order by and apply a running total to the same column without using a temporary table

A representation of my table:
CREATE TABLE Sales
(
id int identity primary key,
SaleAmount numeric(10,2)
);
DECLARE #i INT;
SELECT #i = 1;
SET NOCOUNT ON
WHILE #i <= 100
BEGIN
INSERT INTO Sales VALUES (ABS(CHECKSUM(NEWID()))/10000000.0 );
SELECT #i = #i + 1;
END;
SET NOCOUNT OFF
I need to order my table Sales by SaleAmount and then select all records where a running total of SaleAmount is no greater than X.
To do this I'm currently using a temporary table to first sort the records and then selecting records where the running total is less than or equal to X (in this example 10).
CREATE TABLE #TEMP_TABLE
(
ID integer IDENTITY PRIMARY KEY,
SaleAmount numeric(10,2)
);
INSERT INTO #TEMP_TABLE
(SaleAmount)
SELECT SaleAmount FROM Sales
ORDER BY SaleAmount
SELECT * FROM
(SELECT
Id,
SaleAmount,
(SaleAmount+COALESCE((SELECT SUM(SaleAmount)
FROM #TEMP_TABLE b
WHERE b.Id < a.Id),0))
AS RunningTotal
FROM #TEMP_TABLE a) InnerTable
WHERE RunningTotal <= 10
Is there a way in which I can first order my Sales table without the use of a temporary table?
If you are using SQL Server 2012, then you can just use the window function for cumulative sum:
select s.*,
sum(SaleAmount) over (order by id) as RunningTotal
from Sales s
This is equivalent to the following correlated subquery:
select s.*,
(select sum(SalesAmount) from sales s2 where s2.id <= s.id) as RunningTotal
from Sales s
Following Aaron Bertrand's suggestion of using a cursor method :
DECLARE #st TABLE
(
Id Int PRIMARY KEY,
SaleAmount Numeric(10,2),
RunningTotal Numeric(10,2)
);
DECLARE
#Id INT,
#SaleAmount Numeric(10,2),
#RunningTotal Numeric(10,2) = 0;
DECLARE c CURSOR
LOCAL STATIC FORWARD_ONLY READ_ONLY
FOR
SELECT id, SaleAmount
FROM Sales
ORDER BY SaleAmount;
OPEN c;
FETCH NEXT FROM c INTO #Id, #SaleAmount;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #RunningTotal = #RunningTotal + #SaleAmount;
INSERT #st(Id, SaleAmount, RunningTotal)
SELECT #Id, #SaleAmount, #RunningTotal;
FETCH NEXT FROM c INTO #Id, #SaleAmount;
END
CLOSE c;
DEALLOCATE c;
SELECT Id, SaleAmount, RunningTotal
FROM #st
WHERE RunningTotal<=10
ORDER BY SaleAmount;
This is an increase in code and still requires a table variable. However the improvement in performance is significant.
Credit has to go to Aaron Bertrand for the excellent article on running totals he wrote.
One more option with CTE, ROW_NUMBER() ranking function and APPLY() operator
;WITH cte AS
(
SELECT ROW_NUMBER() OVER(ORDER BY SaleAmount) AS rn, SaleAmount
FROM Sales s
)
SELECT *
FROM cte c CROSS APPLY (
SELECT SUM(s2.SaleAmount) AS RunningTotal
FROM Sales s2
WHERE c.SaleAmount >= s2.SaleAmount
) o
WHERE o.RunningTotal <= 10
FYI, for avoiding operation of sorting you can use this index:
CREATE INDEX ix_SaleAmount_Sales ON Sales(SaleAmount)
After some research, i believe that what your aiming is not possible, unless using SS2012, or Oracle.
Since your solution seems to work i would advise using a table variable instead of a schema table:
DECLARE #TEMP_TABLE TABLE (
ID integer IDENTITY PRIMARY KEY,
SaleAmount numeric(10,2)
);
INSERT INTO #TEMP_TABLE
(SaleAmount)
SELECT SaleAmount FROM Sales
ORDER BY SaleAmount
SELECT * FROM
(SELECT
Id,
SaleAmount,
(SaleAmount+COALESCE((SELECT SUM(SaleAmount)
FROM #TEMP_TABLE b
WHERE b.Id < a.Id),0))
AS RunningTotal
FROM #TEMP_TABLE a) InnerTable
WHERE RunningTotal <= 10
When testing side-by-side, i found some performance improvements.
First of all, you are doing a sub-select and then doing a select * from the sub-select. This is unnecessary.
SELECT
Id,
SaleAmount,
(SaleAmount+COALESCE((SELECT SUM(SaleAmount)
FROM #TEMP_TABLE b
WHERE b.Id < a.Id),0))
AS RunningTotal
FROM #TEMP_TABLE
WHERE RunningTotal <= 10
Now, the temp table is just a query on the Sales table. There is no purpose to ordering the temporary table because by the rules of SQL, the order in the temporary table does not have to be honored, only the order by clause on the outer query, so
SELECT
Id,
SaleAmount,
(SaleAmount+COALESCE((SELECT SUM(SaleAmount)
FROM Sales b
WHERE b.Id < a.Id),0))
AS RunningTotal
FROM Sales
WHERE RunningTotal <= 10