Sql Server 2005 using count and distinct together - sql-server-2005

I'm trying to get the count of each distinct field in my database. For example, we are using something called sourceCodes - I want to be able to see how many of each different sourceCode there is in my database. So far, I have this
SELECT sourceCode, COUNT(DISTINCT sourceCode)
FROM [SecureOrders]
WHERE DateTime >= DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0)
AND DateTime < DATEADD(day, DATEDIFF(day, 0, GETDATE()), 1)
GROUP BY sourceCode
(I'm trying to display the name of the sourceCode first, and then the count). So far though, the only thing I ever get in my second column is "1"...and I'm positive there are more than one. I know I worded this question really poorly, but I can't really figure out any other way to say it. Can anybody see why this is happening?

The "distinct" in your sample is not being applied at the correct place. By grouping by SourceCode, you are already getting distinct values from that column.
So, you only need to count the rows in each group:
SELECT sourceCode, COUNT(*)
FROM [SecureOrders]
WHERE DateTime >= DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0)
AND DateTime < DATEADD(day, DATEDIFF(day, 0, GETDATE()), 1)
GROUP BY sourceCode

Remove the DISTINCT:
SELECT sourceCode, COUNT(sourceCode)
FROM [SecureOrders]
WHERE DateTime >= DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0)
AND DateTime < DATEADD(day, DATEDIFF(day, 0, GETDATE()), 1)
GROUP BY sourceCode

Related

Getting the week number as alias in sql analysis

this is my first question here. Hopefully I´m clear enough what I´m searching for.
My problem is following:
On this analysis I want to get from the last 7 weeks, the summarized prices of each week. Its working with out any problems, but now I would like to add the weeks number of each week as alias.
In my tests I was using for example something like this:
DECLARE #week7 varchar(10)
SET #week7 = DATEPART(wk, GetDate())
One of my problems is, that I´m not allowed to work with "EXEC".
This is just an example of my analysis:
SELECT DISTINCT(
SELECT SUM(Price)
FROM tblBookingdata
WHERE(Datum BETWEEN DATEADD(wk, -7, DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) AND DATEADD(wk, -6, DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))))) AS '7 weeks ago', (
SELECT SUM(Price)
FROM tblBookingdata
WHERE(Datum BETWEEN DATEADD(wk, -6, DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) AND DATEADD(wk, -5, DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))))) AS '6 weeks ago'
I would like the column name to show the week number from each sub select. That the output would be for example for this week: 40 (as column name) and 900 as price summary.
So I tried to work here with DECLARE and assign #week7 for example with the current week number. But here I got stuck, due it seems like I need to work here with EXEC.
Is this only possible with "EXEC" or are there any other solutions to solve this? I was looking in the www, but currently I´m stucking a bit. Thankful for every help! :)
I think the DateDiff function is your friend here. Are you using SQL Server? This won't display a row for the week if there are zero records in that week, but this should be close to what you want.
select WeeksAgo, sum(Price) as Price from (
select
Price
,Datediff(wk, Datum, getDate()) as WeeksAgo
,Datum --not used
from
tblBookingdata
)DataByWeek
where WeeksAgo between 0 and 7 --should this be 0-6?
group by WeeksAgo
I think you're looking for something like this. The prior 7 weeks are calculated from GETDATE based on a numbers table with 1, 2, 3, ... 7. Then the booking Prices are summarized by week where the Datum is within the prior 7 weeks. This will display NULL in price_sum if there were no sales that week.
drop table if exists #tblBookingdata;
go
create table #tblBookingdata(
Datum date not null,
Price int not null);
go
;with
weeks_cte(wk) as (
select datepart(wk, dateadd(wk, w*-1, getdate()))
from (values (1),(2),(3),(4),(5),(6),(7)) v(w)),
bookings_cte(wk, price_sum) as (
select datepart(wk, Datum), sum(Price)
from #tblBookingdata
where Datum>dateadd(wk, -7, getdate())
group by datepart(wk, Datum))
select *
from weeks_cte wc
left join bookings_cte b on wc.wk=b.wk;

SQL Date Queries

Please help me understand the SQL Select statement below:
Select DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()) - 1, 0)
The 0s are throwing me off.
The date 0 is interpreted as 1/1/1900.
This statement is determining the number of days since 1/1/1900:
DATEDIFF(DAY, 0, GETDATE())
It's wrapped in another call that adds that many days, minus 1, to 1/1/1990 (0).
DATEADD(DAY, <from above> - 1, 0)
Essentially giving you yesterday's date.

Weekly to Monthly Reports

I was running weekly reports as in the below script. However, I now want to run monthly report so needed some assistance.
Weekly:
SELECT * FROM TABLE WHERE
(ARRIVAL_DATE>GETDATE()-7)//7 days before
AND
(ARRIVAL_DATE<GETDATE()) //NOW
For monthly report, will below script be right if I run on every 1st?
SELECT Column1,...
FROM TableName
WHERE
MONTH(DateColumn) = MONTH(dateadd(dd, -1, GetDate()))
AND
YEAR(DateColumn) = YEAR(dateadd(dd, -1, GetDate()))
Thanks.
Your logic looks okay, although I would use day instead of dd, because I think it is clearer.
However, your query will prevent the use of an index on datecolumn. The following is a "better" form of the logic, because it allows the use of an index:
where datecolumn >= dateadd(month, -1,
dateadd(day, 1 - day(getdate()), cast(getdate() as date))
) and
datecolumn < dateadd(day, 1 - day(getdate()), cast(getdate() as date))
This looks more complicated, but all the functions are on getdate(), so the engine can use an index. Also note the explicit conversion to date. getdate() returns a time component which might throw off the logic if datecolumn only has a date.
where datecolumn between dateadd(mm, -1,getdate()) and getdate()

Alternative for T-SQL on date calculation for where clause

I have a SQL data calculation which is used as part of where clause to get bookings from calculated date at midnight.
My solution:
bookDate >= (SELECT DATEADD(dd, -7, DATEADD(dd, DATEDIFF(dd, 0, GETDATE()), 0)))
The original was:
bookDate >= DATEADD(dd, -7, GETDATE())
However it returns at calculated date + current time
Is there a alternative and far simpler approach to this?
This is a bit simpler.
bookDate >= DATEADD(dd, DATEDIFF(dd, 0, GETDATE()) - 7, 0)
In SQL Server 2008 and SQL Server 2012 you can use the date data type.
bookDate >= DATEADD(dd, -7, CAST(GETDATE() as DATE))
The following will also work for 2005:
SELECT DATEADD(dd, -7, FLOOR(CAST(GETDATE() AS FLOAT)))
This works because SQL Server (and windows, for that matter) stores a date as a floating point, with the whole number representing the number of days is 01/01/1900, and the fraction part representing the time. The following is shorter, and more consistent with what I usually use in this situation:
SELECT FLOOR(CAST(GETDATE() AS FLOAT) -7)
DATEADD is useful if you're calculating on something other than days (i.e. months, years), because of the varying number of days is each given month or year. When working with days, it's often easier to add or subtract directly. Similarly, if you wanted to subtract, for example, two hours from a date, you can use:
SELECT CAST(GETDATE() AS FLOAT) * 2.0/24.0
You could also do it like this:
bookDate >= CAST(CONVERT(char(8), GETDATE() ,112) as datetime)

Increase SQL Query Performance

Sql:
select distinct DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) as Date,
(select count(*) from Raw_Mats A where DateAdd(Day, DateDiff(Day, 0, A.Receive_date), 0)=DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0)) as Total,
(select count(*) from Raw_Mats B where DateAdd(Day, DateDiff(Day, 0, B.Receive_date), 0)=DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) and B.status='Solved') as Delivered,
(select count(*) from Raw_Mats C where DateAdd(Day, DateDiff(Day, 0, C.Receive_date), 0)=DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) and C.status='Pending') as UnDelivered
from Raw_Mats m where m.Receive_date between '2011-07-01' and '2011-07-21'
How to increase the performance of the above query. It is taking 44 secs . wanna make it less than 10 secs
Thanks
Do you have an index on both Receive_date and status? (not an index on each, combined)
Also:
You have have 4 touches in the table which means the query will scale at least O(4n).
By using COUNT(CASE) you can remove Delivered and UnDelivered subqueries
The simple count subquery isn't needed either
You need GROUP BY. YOur DISTINCT is a work around for that
BETWEEN is >= and <= which isn't the usually correct for dates with times
I've used a subquery here for clarity but it doesn't matter:
select
DateOnly as Date,
COUNT(*) AS Total,
COUNT(CASE WHEN status='Solved' THEN 1 END) AS Delivered,
COUNT(CASE WHEN status='Pending' THEN 1 END) AS UnDelivered
from
(
SELECT
DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) as DateOnly,
status
FROM
Raw_Mats
WHERE
Receive_date >= '2011-07-01' AND Receive_date < '2011-07-21'
) T
GROUP BY
DateOnly
Edit, without subquery.
I started with a subquery because I thought it's be more complex than expected and didn't bother taking it out...
select
DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0) as Date,
COUNT(*) AS Total,
COUNT(CASE WHEN status='Solved' THEN 1 END) AS Delivered,
COUNT(CASE WHEN status='Pending' THEN 1 END) AS UnDelivered
from
Raw_Mats
WHERE
Receive_date >= '2011-07-01' AND Receive_date < '2011-07-21'
GROUP BY
DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0)
Divide and conquer: Just try each part of your sql as a separate statement and you'll find out which part is slow. If you have sub-selects and functions there is a good chance, that the server need temp-tables to perform the select, if you haven't got enough memory (or a large dataset or configured your sql server to do so), this temp-objects are swapped to disk, which makes it slow too.
Too many sub queries man! Get rid of some of them and it will help. Also you should not use functions on both sides in your sqls.
For example:
where DateAdd(Day, DateDiff(Day, 0, A.Receive_date), 0)=
DateAdd(Day, DateDiff(Day, 0, m.Receive_date), 0)
In this specific case the db engine will have to go through all the rows to evaluate DateDiff(Day, 0, A.Receive_date) and DateAdd(Day, DateDiff(Day, 0, A.Receive_date), 0) then compare it with the right hand side which also is a function! This simply is a disaster.
Also, do you have indexes on Receive_date? If not add it.