| Author |
Topic |
|
potn1
Starting Member
33 Posts |
Posted - 2011-05-17 : 00:29:46
|
| I've got a query that is displaying specific months within a date range among other fields. There is a column called total_amount and for a specific month this number is 50. All of the other months have this total_amount as 0. Is there a way I can make all of these other amounts 50 as well? Basically something along the lines of ISNULL(total_amount,50) but I need it to be something that can be generated automatically because the number I am looking to duplicate won't always be 50.Thanks in advance! |
|
|
jackv
Master Smack Fu Yak Hacker
2179 Posts |
Posted - 2011-05-17 : 01:20:53
|
| You could use CASE expression - that allows manipulation of data. Are you able to post your query?Jack Vamvas--------------------http://www.sqlserver-dba.com |
 |
|
|
potn1
Starting Member
33 Posts |
Posted - 2011-05-17 : 09:57:37
|
| SELECT person_id, MONTH(user_date), YEAR(user_date), total_amountFROM personWHERE user_date >= @start_date AND user_date <= @end_dateRight now my query will display all rows within the specific range of dates. The total_amount for 1 of these months would be 50 and the rest would be 0. Basically I just would like a way where I could auto-fill the other rows when the total_amount is 0 to display as 50. These will differ between people so I cannot just use the ISNULL(total_amount,50). Thanks!edit: Would there be a way to select the MAX value from the result and replace that value in my total_amount column for all rows? |
 |
|
|
sunitabeck
Master Smack Fu Yak Hacker
5155 Posts |
Posted - 2011-05-17 : 10:23:09
|
This is picking the max amount for each person_id within the date range you have specifiedSELECT person_id, MONTH(user_date), YEAR(user_date), max(total_amount) OVER (PARTITION BY person_id)FROM personWHERE user_date >= @start_date AND user_date <= @end_date |
 |
|
|
phipywr
Starting Member
6 Posts |
Posted - 2011-05-17 : 11:08:14
|
The method to adjust the value to 50 when zero would be like this:SELECT person_id, MONTH(user_date), YEAR(user_date), case when total_amount = 0 then 50 else total_amount end as total_amountFROM personWHERE user_date >= @start_date AND user_date <= @end_datequote: Originally posted by potn1 SELECT person_id, MONTH(user_date), YEAR(user_date), total_amountFROM personWHERE user_date >= @start_date AND user_date <= @end_dateRight now my query will display all rows within the specific range of dates. The total_amount for 1 of these months would be 50 and the rest would be 0. Basically I just would like a way where I could auto-fill the other rows when the total_amount is 0 to display as 50. These will differ between people so I cannot just use the ISNULL(total_amount,50). Thanks!edit: Would there be a way to select the MAX value from the result and replace that value in my total_amount column for all rows?
Have an ordinary day |
 |
|
|
potn1
Starting Member
33 Posts |
Posted - 2011-05-17 : 11:20:38
|
quote: Originally posted by sunitabeck This is picking the max amount for each person_id within the date range you have specifiedSELECT person_id, MONTH(user_date), YEAR(user_date), max(total_amount) OVER (PARTITION BY person_id)FROM personWHERE user_date >= @start_date AND user_date <= @end_date
I tested this on person_id 18 who has 5 records (Jan,Feb,March,Apr,May) between the date range and it seems to be leaving the other values as 0. February is the only month where they have a total_amount of 50. January, March, April and May the total_amount is 0. I am trying to get those 4 other months to also display a total_amount of 50. Is what you posted supposed to work for what I'm looking for?Thanks! |
 |
|
|
potn1
Starting Member
33 Posts |
Posted - 2011-05-17 : 11:23:31
|
quote: Originally posted by phipywr The method to adjust the value to 50 when zero would be like this:SELECT person_id, MONTH(user_date), YEAR(user_date), case when total_amount = 0 then 50 else total_amount end as total_amountFROM personWHERE user_date >= @start_date AND user_date <= @end_datequote: Originally posted by potn1 SELECT person_id, MONTH(user_date), YEAR(user_date), total_amountFROM personWHERE user_date >= @start_date AND user_date <= @end_dateRight now my query will display all rows within the specific range of dates. The total_amount for 1 of these months would be 50 and the rest would be 0. Basically I just would like a way where I could auto-fill the other rows when the total_amount is 0 to display as 50. These will differ between people so I cannot just use the ISNULL(total_amount,50). Thanks!edit: Would there be a way to select the MAX value from the result and replace that value in my total_amount column for all rows?
Have an ordinary day
But the value will not always be 50 that I want displayed. It will be the MAX value of total_amount returned per each specific person_id. So replacing 0 with 50 would only work for this specific person.Is there anyway to use a CASE when total_amount is 0 to replace that with the MAX total_amount from a dataset? |
 |
|
|
sunitabeck
Master Smack Fu Yak Hacker
5155 Posts |
Posted - 2011-05-17 : 12:40:45
|
quote: Originally posted by potn1
quote: Originally posted by sunitabeck This is picking the max amount for each person_id within the date range you have specifiedSELECT person_id, MONTH(user_date), YEAR(user_date), max(total_amount) OVER (PARTITION BY person_id)FROM personWHERE user_date >= @start_date AND user_date <= @end_date
I tested this on person_id 18 who has 5 records (Jan,Feb,March,Apr,May) between the date range and it seems to be leaving the other values as 0. February is the only month where they have a total_amount of 50. January, March, April and May the total_amount is 0. I am trying to get those 4 other months to also display a total_amount of 50. Is what you posted supposed to work for what I'm looking for?Thanks!
This is most likely because your @start_date and @end_date cover only February. The query is really looking within the date range you specified via those two variables, picking up the largest value, and assigning that value to all the rows WITHIN that date range.If you want to ignore the date range while picking the value to be used, then you could do the following:;WITH Totals AS( SELECT person_id, MAX(total_amount) AS TotalForUser GROUP BY person_id)SELECT p.person_id, MONTH(user_date), YEAR(user_date), TotalForUserFROM person p INNER JOIN Totals t ON t.person_id = p.person_idWHERE user_date >= @start_date AND user_date <= @end_date |
 |
|
|
potn1
Starting Member
33 Posts |
Posted - 2011-05-17 : 14:07:20
|
| Is Totals basically a temporary table that determines each person_id MAX total_amount and then you grab that data to display within your query? |
 |
|
|
phipywr
Starting Member
6 Posts |
Posted - 2011-05-17 : 14:43:59
|
In my example 50 would be used for any person who had 0 in the amount. To use the max amount, one way to do it would be to use a subselect. (Note I also cleaned up the where clause)SELECT person_id, MONTH(user_date), YEAR(user_date), case when total_amount = 0 then (select max(total_amount) from person) else total_amount end as total_amountFROM personWHERE user_date between @start_date and @end_dateIf you have a lot of rows that are zero this could be a little slow, though.If you are creating a stored procedure, you could set a variable to the max amount and then just use that variable in your case statement instead.quote: Originally posted by potn1 [quote]Originally posted by phipywr The method to adjust the value to 50 when zero would be like this:SELECT person_id, MONTH(user_date), YEAR(user_date), case when total_amount = 0 then 50 else total_amount end as total_amountFROM personWHERE user_date >= @start_date AND user_date <= @end_dateBut the value will not always be 50 that I want displayed. It will be the MAX value of total_amount returned per each specific person_id. So replacing 0 with 50 would only work for this specific person.Is there anyway to use a CASE when total_amount is 0 to replace that with the MAX total_amount from a dataset?
Have an ordinary day |
 |
|
|
sunitabeck
Master Smack Fu Yak Hacker
5155 Posts |
Posted - 2011-05-17 : 14:55:28
|
quote: Originally posted by potn1 Is Totals basically a temporary table that determines each person_id MAX total_amount and then you grab that data to display within your query?
It is a CTE (common table expression), which conceptually you can think of as a temporary table or table variable - but there are some important differences. |
 |
|
|
jimf
Master Smack Fu Yak Hacker
2875 Posts |
Posted - 2011-05-17 : 14:58:05
|
Nice work! JimEveryday I learn something that somebody else already knew |
 |
|
|
phipywr
Starting Member
6 Posts |
Posted - 2011-05-18 : 10:21:19
|
In our shop CTE's have invariably performed really poorly. My testing revealed that using table variables or temp tables (depending upon size of results) was always significantly faster. Any idea why?quote: Originally posted by sunitabeck
quote: Originally posted by potn1 Is Totals basically a temporary table that determines each person_id MAX total_amount and then you grab that data to display within your query?
It is a CTE (common table expression), which conceptually you can think of as a temporary table or table variable - but there are some important differences.
|
 |
|
|
sunitabeck
Master Smack Fu Yak Hacker
5155 Posts |
Posted - 2011-05-18 : 10:30:29
|
| I have seen improved performance with temp tables in many cases, but not with table variables, especially when you add indexes to the temp tables. You cannot add indexes to CTE's or table variables.I have seen improved performance with temp tables even without indexes sometimes - my guess is that that is because when you use temp tables, each individual transaction is smaller, involving fewer tables - but I am speculating. |
 |
|
|
potn1
Starting Member
33 Posts |
Posted - 2011-05-23 : 14:24:15
|
| Right now this query will display a row for every month within the date range. Only one of these rows will have data in every column. Basically if I select a range of 9 months, person_id of 18 will only show up in the row with data. The other 8 rows will show NULL for the person_id column. Is there a way I can get the person_id of 18 to show up in every other row of this query? I think a TOP 1 needs to be used but when I try to do that in my initial select statement it says that the PersonInfo table does not exist. Are you not able to select the top value from a subquery? ThanksSELECT PersonInfo.person_id, Calendar.MNumber, Calendar_Year.MName,Calendar_Year.Year,total_amountFROM (select distinct MNumber, MName from Calendar_Year) CalendarLEFT JOIN (SELECT person_id, MNumber, MName, Year, ISNULL(total_amount,0) as total_amount, FROM person p WHERE user_date >= @start_date AND user_date <= @end_date AND person_id = 19) AS PersonInfoON Calendar.MNumber = PersonInfo.MNumberLEFT JOIN Calendar_Year ON Calendar_Year.MNumber = Calendar.MNumber |
 |
|
|
potn1
Starting Member
33 Posts |
Posted - 2011-05-24 : 10:31:49
|
| Any ideas? When I try to SELECT values from PersonInfo it says the table does not exist, is there anyway to SELECT a top value from a subquery? |
 |
|
|
|