Query is not grouping - sql-server

Im filling a table and I need this table get the daily sells, but summing and counting, sells and clients by day respectively.
But is not grouping the sales by day this is the QUERY:
insert into VentaDiariaTienda(
Fecha,
VentaDia,
Tda_Codigo,
NumeroClientes,
PromedioVtaCliente,
EditName,
EditDateTime)
select
DATENAME(dw, T_Fecha) + ', ' +
cast(datepart(dd, T_Fecha) as char(2)) + ' ' +
datename(mm, T_Fecha) + ' ' +
cast(datepart(yyyy,T_Fecha) as char(4)),
sum(T_ImporteTotal/1.16),
[FolTda_Codigo],
count(T_Cliente),
sum(T_ImporteTotal/1.16)/count(T_Cliente),
'Admin',
GETDATE()
from #Tickets
group by T_Fecha,[FolTda_Codigo]
and this is the out of this query
Thanks for your replys.

You will have to "round down" the T_Fecha values to a day, so you might try to insert the following records:
SELECT
DATENAME(dw, dt) + ', ' +
DATENAME(dd, dt) + ' ' +
DATENAME(mm, dt) + ' ' +
DATENAME(yy, dt),
SUM(T_ImporteTotal)/1.16,
FolTda_Codigo,
COUNT(T_Cliente),
SUM(T_ImporteTotal)/1.16/COUNT(T_Cliente),
'Admin',
GETDATE()
FROM #Tickets
CROSS APPLY (
VALUES (DATEADD(day, DATEDIFF(day, 0, T_Fecha), 0))
) d (dt)
GROUP BY dt, FolTda_Codigo

My proposition:
You can use format function (since SQL Server 2012, else use Wolfgang Method)
Be carefull with divide by "Count" function. If you result is 0 (by example if T_Client is always null) you will have an error
Not necessary to use "outer apply" instruction in this case, group on by date and not by date and time
Something like this:
SELECT
FORMAT(T_Fecha, 'dddd, dd MMMM yyyy', 'en-US' ),
SUM(T_ImporteTotal)/1.16,
FolTda_Codigo,
COUNT(T_Cliente),
case when COUNT(T_Cliente)=0 then null else SUM(T_ImporteTotal)/1.16/COUNT(T_Cliente) end,
'Admin',
GETDATE()
FROM #Tickets
GROUP BY cast(T_Fecha as date), FolTda_Codigo
For SQL Server 2008, replace format by
DATENAME(dw, T_Fecha) + ', ' + DATENAME(dd, T_Fecha) + ' ' +
DATENAME(mm, T_Fecha) + ' ' + DATENAME(yy, T_Fecha),

Related

Use MAX(Date) value inside a SQL recursion

I have SQL query with performs recursion based on selected Min(Date) and Max(Date) from more than 1 table. But when i try to run the query it throws GROUP BY, HAVING, or aggregate functions are not allowed in the recursive part of a recursive common table expression 'ctedaterange'. exception. I also tried using Top 1 Date but still no hope.
SQL Query
ALTER VIEW [dbo].[CYExtraction]
AS
WITH ctedaterange
AS (SELECT
[Dates] = (SELECT
MIN(CreatedOn) AS CreatedOn
FROM (SELECT
MIN(CreatedOn) AS CreatedOn
FROM (SELECT
MIN(CreatedOn) AS CreatedOn
FROM Items) AS it
UNION ALL
SELECT
*
FROM (SELECT
MIN(CreatedOn) AS CreatedOn
FROM Bibs) AS bib
UNION ALL
SELECT
*
FROM (SELECT
MIN(CreatedOn) AS CreatedOn
FROM Porders) AS po) AS AllItems)
UNION ALL
SELECT
[dates] + 1
FROM ctedaterange
WHERE [dates] + 1 <= (SELECT
MAX(CreatedOn) AS CreatedOn
FROM (SELECT
MAX(CreatedOn) AS CreatedOn
FROM (SELECT
MAX(CreatedOn) AS CreatedOn
FROM Items) AS it
UNION ALL
SELECT
*
FROM (SELECT
MAX(CreatedOn) AS CreatedOn
FROM Bibs) AS bib
UNION ALL
SELECT
*
FROM (SELECT
MAX(CreatedOn) AS CreatedOn
FROM Porders) AS po) AS AllItems))
SELECT
[Dates] AS PK_Date,
DATENAME(MONTH, [Dates]) + ' ' + CAST(YEAR([Dates]) AS varchar(4)) AS
Month,
CASE
WHEN DATEPART(m, [Dates]) <= 3 THEN 'Q1 ' + CAST(YEAR([Dates]) AS varchar(4))
ELSE CASE
WHEN DATEPART(m, [Dates]) <= 6 THEN 'Q2 ' + CAST(YEAR([Dates]) AS varchar(4))
ELSE CASE
WHEN DATEPART(m, [Dates]) <= 9 THEN 'Q3 ' + CAST(YEAR([Dates]) AS varchar(4))
ELSE CASE
WHEN DATEPART(m, [Dates]) <= 12 THEN 'Q4 ' + CAST(YEAR([Dates]) AS varchar(4))
ELSE ''
END
END
END
END AS 'Quarter',
CASE
WHEN DATEPART(m, [Dates]) <= 6 THEN 'HY1 ' + CAST(YEAR([Dates]) AS varchar(4))
ELSE CASE
WHEN DATEPART(m, [Dates]) <= 12 THEN 'HY2 ' + CAST(YEAR([Dates]) AS varchar(4))
ELSE ''
END
END AS 'HalfYear',
YEAR([Dates]) AS 'Year',
CAST('1-' AS varchar(5)) + CAST(DATEPART(M, [Dates]) AS varchar(10)) + '-' + CAST(YEAR([Dates]) AS varchar(4)) AS DateName
FROM ctedaterange
GO
The main thing is that I need to wrap it inside my SQL Views. Any help to my problem will be appreciated.
Thanks,
You can move the aggregations to an extra cte, so this might be what you want:
ALTER VIEW [dbo].[CYExtraction]
(PK_Date, [Month], [Quarter], [HalfYear], [Year], [DateName])
AS
WITH cteAllItems (mindates, maxdates) AS (
SELECT MIN(CreatedOn), MAX(CreatedOn) FROM Items
UNION ALL
SELECT MIN(CreatedOn), MAX(CreatedOn) FROM Bibs
UNION ALL
SELECT MIN(CreatedOn), MAX(CreatedOn) FROM Porders
),
ctedaterange (Dates, MaxDate) AS (
SELECT MIN(mindates), MAX(maxdates)
FROM cteAllItems
UNION ALL
SELECT DATEADD(day, 1, Dates), MaxDate
FROM ctedaterange
WHERE DATEADD(day, 1, Dates) <= MaxDate
)
SELECT
Dates AS PK_Date,
DATENAME(MONTH, Dates) + N' ' + DATENAME(YEAR, Dates),
N'Q' + DATENAME(QUARTER, Dates) + N' ' + DATENAME(YEAR, Dates),
N'HY' + CAST((MONTH(Dates)-1)/6+1 AS nvarchar(1)) + N' ' + DATENAME(YEAR, Dates),
YEAR(Dates),
CONVERT(nvarchar(10), DATEADD(MONTH, DATEDIFF(MONTH, 0, Dates), 0), 105)
FROM ctedaterange
GO

Issue with a WHERE clause

I any writing a query in SQL Server to display all jobs which were received in the previous week, the query will be the basis of an automated report in Crystal Report, syntax is as below
SELECT TOP (100) PERCENT
DATENAME(yy, dbo.JOB.JOB_TAKEN_DATE) + '-' + DATENAME(wk, DATEADD(wk, - 1, dbo.JOB.JOB_TAKEN_DATE)) AS PERIOD,
dbo.JOB.CUST_ORD_NO AS [ORDER NO],
dbo.JOB.JOB_TAKEN_DATE AS RECEIVED,
dbo.JOB.JOB_COMPLETION_DATE AS COMPLETED,
UPPER(ISNULL(dbo.JOB.PROPERTY_LOCATION, ' ') + ' ' + dbo.JOB.PROPERTY_NAME + ' ' + REPLACE(REPLACE(REPLACE(dbo.JOB.PROPERTY_ADDRESS, CHAR(10), ' '), CHAR(13), ' '), CHAR(9), ' ') + ' ' + dbo.JOB.PROPERTY_POSTCODE) AS ADDRESS,
REPLACE(REPLACE(REPLACE(dbo.JOB.WORKS_TO_BE_CARRIED_OUT, CHAR(10), ' '), CHAR(13), ' '), CHAR(9), ' ') AS [WORKS ORDERED],
dbo.JOB.JOB_TARGET_DATE,
dbo.['TMO properties$'].F2
FROM
dbo.JOB
INNER JOIN
dbo.CUSTOMERPROPERTY ON dbo.JOB.CUSTOMER_PROPERTY_ID = dbo.CUSTOMERPROPERTY.CUSTOMER_PROPERTY_ID
INNER JOIN
dbo.['TMO properties$'] ON dbo.CUSTOMERPROPERTY.EXTERNAL_REFERENCE = dbo.['TMO properties$'].F1
WHERE
DATENAME(yy, dbo.JOB.JOB_TAKEN_DATE) + '-' + DATENAME(wk, DATEADD(wk, - 1, dbo.JOB.JOB_TAKEN_DATE)) = DATENAME(yy, CURRENT_TIMESTAMP) + '-' + DATENAME(wk, DATEADD(wk, - 1, CURRENT_TIMESTAMP))
ORDER BY
RECEIVED
When running the query I get an error
adding a value to a 'date' column caused an overflow
Can anyone see what I am doing wrong?
The only place your error could be coming from in the code provided is:dateadd(week, -1, j.job_taken_date) which appears in both your select and your where.
You can get around this by using datepart() to get the week integer and reducing that by 1 instead of adjusting the date value with: convert(varchar(2),datepart(week,j.job_taken_date)-1).
It looks like your where clause means "jobs taken this week". If that is the case, you can simplify your where to compare dates truncated to the week instead of the string comparison you are building now, which may be causing your error.
You can also make your query easier to read by using table aliases, and not using shorthand with date/time operations.
select top (100) percent
datename(year, j.job_taken_date)
+ '-'
--+ datename(week, dateadd(week, -1, j.job_taken_date)
+ convert(varchar(2),datepart(week,j.job_taken_date)-1)
) as period
, j.cust_ord_no as [order no]
, j.job_taken_date as received
, j.job_completion_date as completed
, upper(isnull(j.property_location, ' ')
+ ' ' + j.property_name + ' '
+ replace(replace(replace(j.property_address, char(10), ' '), char(13), ' '), char(9), ' ')
+ ' ' + j.property_postcode
) as address
, replace(replace(replace(j.works_to_be_carried_out, char(10), ' '), char(13), ' '), char(9), ' '
) as [works ordered]
, j.job_target_date
, tmop.F2
from dbo.job j
inner join dbo.customerproperty cp
on j.customer_property_id = cp.customer_property_id
inner join dbo.['tmo properties$'] tmop
on cp.external_reference = tmop.F1
where dateadd(week, datediff(week, 0, j.job_taken_date), 0)
= dateadd(week, datediff(week, 0, current_timestamp), 0)
order by received

SQL server date time

I am trying to get object which its start date + start time have passed or equal to current datetime and its end date + end time hasn't pass the current datetime. I tried convert current datetime to nvarchar as all my columns are nvarchar. I also tried converting my columns to datetime type but it doesn't work too. Please help
Column:
startDate - nvarchar (dd/mm/yyyy)
startTime - nvarchar (hh:mm) 24 hr
endDate - nvarchar(dd/mm/yyyy)
endTime - nvarchar(hh:mm) 24hr
i did try to but datetime betwween startDate + startTime AND endDate +startTime,
but it doesn't seems to work :
SELECT * FROM Promo
WHERE membership = '1'
AND promoStatus = '1'
AND CONVERT(NVARCHAR, GetDate(), 101) + ' ' +
CONVERT(NVARCHAR, DATEPART(hh, GetDate())) + ':' +
RIGHT('0' + CONVERT(NVARCHAR, DATEPART(mi, GetDate())), 2) BETWEEN
startDate + ' ' + startTime
AND endDate + ' ' + endTime
i did try other method too :
SELECT * FROM Promo
WHERE membership = '1'
AND promoStatus = '1'
AND startDate + ' ' + startTime <= CONVERT(NVARCHAR, GetDate(), 101) + ' ' +
CONVERT(NVARCHAR, DATEPART(hh, GetDate())) + ':' +
RIGHT('0' + CONVERT(NVARCHAR, DATEPART(mi, GetDate())), 2)
AND endDate + ' ' + endTime >= CONVERT(NVARCHAR, GetDate(), 101) + ' ' +
CONVERT(NVARCHAR, DATEPART(hh, GetDate())) + ':' +
RIGHT('0' + CONVERT(NVARCHAR, DATEPART(mi, GetDate())), 2)
You could do it like this:
SELECT *
FROM Promo
WHERE
membership = '1'
AND promoStatus = '1'
AND CAST(CONVERT(VARCHAR(16), GETDATE(), 120) AS DATETIME) BETWEEN
CONVERT(DATETIME, #startDate, 103) + CONVERT(DATETIME, #startTime)
AND CONVERT(DATETIME, #endDate, 103) + CONVERT(DATETIME, #endTime)
This line:
CAST(CONVERT(VARCHAR(16), GETDATE(), 120) AS DATETIME)
gets the current date time up to its minutes, meaning this will strip off the seconds and milliseconds part of the GETDATE().
And this line:
CONVERT(DATETIME, #startDate, 103) + CONVERT(DATETIME, #startTime)
will combine your date and time variables to form a new DATETIME value.
Note that you could have done away with with this if you design the tables using the proper data types.
Try this
SELECT * FROM Promo
WHERE membership = '1'
AND promoStatus = '1'
AND CAST(CONVERT(VARCHAR(16), GetDate(), 120) AS DATETIME)
BETWEEN CONVERT(DATETIME, startDate + ' ' + startTime, 120)
AND CONVERT(DATETIME, endDate + ' ' + endTime, 120)

SQL query taking very long to execute

I have two versions of the same query which I'm trying to execute on SQL Server 2008.
Version 1:
select
count(a.ordernumber) as Orders,
sum(b.agentfees) as AgentFees,
sum(a.revenue) as Revenue,
CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) as Date
from
orders a
join
[DC-SQL-V2].FaxFile.dbo.[agent fees] b on a.ordernumber = b.fforder
where
a.closeoutdate >= '2014-01-01'
and b.dtcreated >= '2014-01-01'
and a.closeoutdate < '2015-01-01'
and b.dtcreated < '2015-01-01'
and a.processserving = 1
and a.branchno = '116'
group by
CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date)
order by
CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date)
Version 1 takes around 3 hours to finish which is obviously insane. So I created Version 2 in which I tried to filter the tables first before joining them, but this still takes pretty long (2 hours and still going).
Version 2:
select
count(a.ordernumber) as Orders,
sum(b.agentfees) as AgentFees,
sum(a.revenue) as Revenue,
CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) as Date
from
(select
ordernumber, revenue, closeoutdate, processserving, branchno
from
ORDERS
where
closeoutdate >= '2014-01-01'
and closeoutdate < '2015-01-01'
and branchno = '116'
and processserving = 1) a
join
(select
agentfees, fforder, dtcreated
from
[DC-SQL-V2].FaxFile.dbo.[agent fees]
where
dtcreated >= '2014-01-01'
and dtcreated < '2015-01-01') b on a.ordernumber = b.fforder
group by
CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date)
order by
CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date)
Here are some additional details:
select count(*) from [DC-SQL-V2].FaxFile.dbo.[agent fees]
779531
select count(*) from ORDERS
3466648
Here are the clustered columns for both tables (among others that I'm not selecting):
ORDERS:
BranchNo
Closeoutdate
ProcessServing
AGENT FEES:
Nothing I'm selecting is clustered
Would someone please be able to suggest how I can improve the performance of my queries?
Assuming [DC-SQL-V2] is a remote, linked server, I'd recommend bringing that data local first.
/* Making broad assumptions here. Substitute correct data types */
CREATE TABLE #tmpAgentFees (
agentfees money,
fforder int,
dtcreated datetime
);
INSERT INTO #tmpAgentFees
(agentfees, fforder, dtcreated)
SELECT agentfees, fforder, dtcreated
FROM [DC-SQL-V2].FaxFile.dbo.[agent fees]
WHERE dtcreated >= '2014-01-01'
AND dtcreated < '2015-01-01';
/* Optionally, add an index to perhaps help performance of the join */
CREATE INDEX IX_tmpAgentFees_fforder
ON #tmpAgentFees(fforder)
INCLUDE (agentfees, dtcreated);
select count(a.ordernumber) as Orders, sum(b.agentfees) as AgentFees, sum(a.revenue) as Revenue,
CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) as Date
from orders a
join #tmpAgentFees b
on a.ordernumber = b.fforder
where a.closeoutdate >= '2014-01-01'
and a.closeoutdate < '2015-01-01'
and a.processserving=1
and a.branchno='116'
group by
CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date)
order by
CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date)
There are some general hints
use SQL Server Profiler to find the most costly part
use an index on join column fforder
CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) is repeated again and again, if it is possible create a computer column in your table and store the value and create an index on this new column with include in index option on
if 3 is not possible use drive table for example as below
select * from
(
select col1,col2,..,CAST('1/' + CAST(DATEPART(Month, a.closeoutdate) as varchar) + '/' + CAST(DATEPART(Year, a.closeoutdate) as varchar) as Date) from table1 ) drivedTable
join .....
The costly part is where you are getting detail data from the foreign server and then summarizing it. You should summarize it their and then only bring that back. It is not clear to me how "dtcreated" and "closeoutdate" are related?
Below I summarized the data by month and then brought it over to the local server. So only 12 rows are coming over instead of one per order. This may not be what you want if the fee should be counted in the "closeoutdate" month. But your code had a problem where it would never count an order or fee if there dates were in different years. (Need to clarify what is needed with that.)
select
a.CloseMonth,
a.Orders,
b.AgentFees
a.Revenue
from
(select year(closeoutdate) * 100 + month(closeoutdate) as CloseMonth,
count(a.ordernumber) as Orders,
sum(a.revenue) as Revenue
from orders
where closeoutdate >= '2014-01-01'
and closeoutdate < '2015-01-01'
and branchno = '116'
and processserving = 1
group by year(closeoutdate) * 100 + month(closeoutdate)) as a
join
(select year(dtcreated) * 100 + month(dtcreated) as FeeMonth,
sum(agentfees) AgentFees
from [DC-SQL-V2].FaxFile.dbo.[agent fees]
where
dtcreated >= '2014-01-01'
and dtcreated < '2015-01-01'
group by year(dtcreated) * 100 + month(dtcreated)) b
on a.CloseMonth = b.FeeMonth
order by a.CloseMonth

sql server year

DECLARE #FINANCIALYEAR AS varchar(30)
DECLARE #FINALFINANCIALYEAR AS int
SELECT #FINANCIALYEAR=CONVERT(VARCHAR,YEAR(GETDATE())-2) + ', ' +
CONVERT(VARCHAR,YEAR(GETDATE())-1) + ', ' +
CONVERT(VARCHAR,YEAR(GETDATE()))
set #FINALFINANCIALYEAR = CONVERT(int,#FINANCIALYEAR)
print #FINALFINANCIALYEAR
i want final output in int format so iam doing above code but it gives me error plz help
Simple query
SELECT CONVERT(VARCHAR,YEAR(GETDATE())-2) + ', ' +
CONVERT(VARCHAR,YEAR(GETDATE())-1) + ', ' +
CONVERT(VARCHAR,YEAR(GETDATE()))
Select YEAR (GetDate())-2,YEAR (GetDate())-1, YEAR (GetDate())
Just check what your variable is after your SELECT:
DECLARE #FINANCIALYEAR AS varchar(30)
DECLARE #FINALFINANCIALYEAR AS int
SELECT #FINANCIALYEAR=CONVERT(VARCHAR,YEAR(GETDATE())-2) + ', ' +
CONVERT(VARCHAR,YEAR(GETDATE())-1) + ', ' +
CONVERT(VARCHAR,YEAR(GETDATE()))
SELECT #FINANCIALYEAR
The output is:
2008, 2009, 2010
This is clearly NOT a valid INT value - so it's obvious you're getting a conversion error.....
SELECT DATEPART(YEAR, GETDATE()), DATEPART(YEAR, GETDATE()) - 1, DATEPART(YEAR, GETDATE()) - 2
this year is
Select datepart(year,getdate())
or
year(getdate())

Resources