Inner join query logic - sql-server

I am using Sql Server Management studio.
I have the following table.
when i run the following query I get the running total for sales column
select s1.date,
sum(s2.sales)
from sales s1
join sales s2 on s1.date>=s2.date
group by s1.date;
but when i substitute s2.sales with s1.sales in the select
select s1.date,
**sum(s1.sales)**
from sales s1
join sales s2 on s1.date>=s2.date
group by s1.date;
it gives me a different answer can someone help me understand why i am facing this? since the sales column value should be the same.

The first version of your running total query is summing sales, for each dates, over dates which are strictly less than or equal to the date in each record. When you change s2.sales to s1.sales, you are then summing the current record's sales N number of times, where N is the number of records having an earlier date. This clearly is not the logic you want, so stick with the first version.
By the way, if you're using MySQL 8+, then analytic functions simplify things even further:
SELECT Date, Sales, SUM(Sales) OVER (ORDER BY Date) RunningSales
FROM sales
ORDER BY Date;

Related

SQL Error message: Column XXX is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

SELECT
t.[Week], MAX(t.Revenue) AS 'Max Revenue'
FROM
(SELECT
[Week], SUM([Service Total]) AS Revenue
FROM
dbo.['Data - 2017 Appmt Time$']
GROUP BY
[Week]) t;
Error:
Column 't.Week' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
What I'm trying to do is to get the max revenue and the respective week for which is that max revenue. How to make that code working? The code is working if I don't select t.[Week] in the beginning but then I get only the max revenue. If I include t.[Week] in a group by clause, as the message suggests, that I have a list of all revenues week-by-week, but I don't need it. I only need the max revenue and for which week it is.
Apologies if my question is stupid, I'm a beginner in SQL and already lost much time searching for a solution. :( Thanks a lot in advance!
You cannot use a non aggregate column in select which is not part of Group By.
Actually you don't need derived table for this, to find the week with maximum revenue use TOP 1 with Order by
SELECT top 1 [Week],
Revenue = SUM([Service Total])
FROM dbo.['Data - 2017 Appmt Time$']
GROUP BY [Week]
order by Revenue desc
As mentioned by Dan Guzman, if there is a tie in maximum revenue and you want all the tie records then replace TOP 1 with TOP 1 with Ties

SQL Server 2014 Management Studio

I'm a non profit lawyer trying to set up a SQL Server database for my agency. The issue I'm having is query based: I need a simple query that will aggregate the total number of rows on a table, not the sum of the cell contents.
I working with 4 columns of I to: attorney's name, client name, trial date and remedy (the last 2 are date and dollar amount, so integers].
*** Script for SelectTopNRows command from SSMS***
SELECT TOP 100
[attorney]
,[client]
,[trial_date]
,[remedy]
FROM [MyLegalDB]
WHERE [trial_date] between '20160101' and '20160531'
I'm trying to find a way (script, batch file, etc) that will populate a total number of cases by month (according to trial date) total number of clients, and sum the remedy column.
Sorry for the vagueness. There are privilege rules in place. Hope that helps clarify.
Thanks
Assuming that your case history spans years, not just months, try this:
SELECT
,YEAR([trial_date]) AS [Year]
,MONTH([trial_date]) AS [Month]
,COUNT(1) AS [Trial_Count]
FROM [MyLegalDB]
WHERE [trial_date] between '20160101' and '20160531'
GROUP BY YEAR([trial_date]), MONTH([trial_date])
If you want to separate this by attorney, you would need to add that column to the SELECT list, as well as the GROUP BY clause, as such:
SELECT
[attorney]
,YEAR([trial_date]) AS [Year]
,MONTH([trial_date]) AS [Month]
,COUNT(1) AS [Trial_Count]
FROM [MyLegalDB]
WHERE [trial_date] between '20160101' and '20160531'
GROUP BY [attorney], YEAR([trial_date]), MONTH([trial_date])
This is a very general answer to a very general question. If you want me to be more specific, I'm going to have to understand your goal a little better. Hope it helps.

SQL Server find column difference from different tables and fill intermediate dates

I have the purchase entry in one table #temp1 and sales history in another table #temp2 for multiple stores. There might be no sales, no purchase, or both/either of them in a day. I need to build a graph of daily stock.
Basically, I am stuck in the query part. For first part I need to combine both tables to view the data together...
Secondly, I need to find the cumulative values for the stock ; something like ...
After I get I need to plot it finally... help out !!! QUERY MASTER !!!
If you start out by using a Union something like:
SELECT Store, Date, Purchase, 0 Sales FROM #temp1
UNION ALL
SELECT Store, Date, 0, Sales FROM #temp2
You have all the data in one table/view. From there, you can get things consolidated by
SELECT
Store, Date,
Sum(Purchase) Purchase,
Sum(Sales) Sales,
Sum(Purchase) - Sum(Sales) InStock
GROUP BY
Store, Date
That will give you a view with the Store, Date, Purchases, Sales and In Stock in one row. If you work things via query rather than temp tables, you can easily use the final view to feed SSRS and draw your graph.
Hope that helps.
Yes, the hint by #mark worked...
select store,date,ISNULL(purchase,0) as purchase,0 as sales
into #tbl
from temp1
union all
select store,date,0 as purchase,ISNULL(sales,0) as sales from temp2
select store,sum(purchase) as PUR,sum(sales) as SAL,sum(purchase-sales) as STOCK from #tbl
group by store,date
order by storename
drop table #tbl
And, the empty dates in between are automatically managed by the SSRS reporting tool.
But, the cumulative sums are not able to solve till now...

Compute sum for distinct order numbers in ssrs report

I'm using a SQL Server 2008R2 Database and SSRS Report Builder 3.0
Trying to compute the sum of the amount owed for each order id (need to show the itemids)...but when I do, the amount owed is showing 400 (instead of 200 - line 4, 100 instead of 50 in line 7, line 9 is correct. As a result the Total line is way off)
=Sum(Fields!owe.Value)
The report is grouped by the campus.
I understand that ssrs is probably not the best place to do this computation but I don't know how to do outside of ssrs....I tried distinct and group by so far with no results.
Below is how I need the report to show like....
Thanks in advance.
Incorrect amounts are
Another example as it should display the subtotals
I would modify the SQL to produce an extra column just for purposes of summing the Owe on an OrderId. Use the Row Number to get the first item in each order, and only supply the Owe value for that item for each order:
WITH cte AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY OrderId ORDER BY ItemId) AS rn
FROM MyTable
WHERE (whatever filters you use)
)
SELECT *,
CASE WHEN rn=1 THEN Owe ELSE 0 END AS OrderOwe
FROM cte
ORDER BY Campus, CustomerId, OrderId, ItemId
Then simply change the expression for the "Owe" textbox in your SubTotal row to this:
=Sum(Fields!OrderOwe.Value)
And you will get the sum of the Owe per order instead of per item.
Well if your owe is always the same for each item in the group you could add a Sum/Count of the item in the group which would give you the correct results in all the cases above.

SQL - Stored Procedures for reporting using Reporting Service

I'm using Reporting Service in a ASP.NET MVC4 project (using Visual Studio 2010) to generate reports and I'm working with stored procedures. I have a table Product which can belong to persons. That's the concept of allocation. A product can be allocated to different persons (many-to-many relation) and I have an intermediate table between those two :
The thing I want tot do in my report is to display the information related to each existing product including the owner. In this situation, I can have 2 types of owners : the company (so the product has never been allocated or the last allocation has an EndDate) or a person (so the last allocation doesn't have an EndDate or has a "future" EndDate).
I know that all these verifications should be made in my report template but for the SQL stored procedure, I have no idea about how to do to get the last allocation for each product (if there is any).
Any idea which could help is welcomed.
EDIT : Updated query
SELECT pr.SerialNumber, coalesce (p.LastName, 'US') as Owner
FROM bm_Products pr
LEFT OUTER JOIN
(Select Id_Person, Id_Product, max(ISNULL(EndDate,getdate()+1)) as MaxAllocDate
FROM bm_ProductAllocations a
WHERE EndDate > getdate()
group by Id_Person, Id_Product
having max(ISNULL(EndDate, getdate()+1)) =
(select max(isnull(EndDate, getdate()+1))
from bm_ProductAllocations where Id_Product = a.Id_Product)
) pa on pr.Id_Product = pa.Id_Product
LEFT OUTER JOIN bm_Persons p on pa.Id_Person = p.Id_Person
The result :
SerialNumber Owner
-------------------------------------------------- --------------------------------------------------
78745148154815204 US
84512048150410522 US
84512841520415205 US
87451284512485120 US
56123051215215215 US
48512485487487856 US
CNU1510ZL0 US
8456656551521 US
4154854854151 US
4851205230047 US
4511120521050 US
84515151320541201 US
74161230326524165 US
I don't see "company" for owner on the table shown, so i'll assume for now that it is in the products table, a hardcoded 'US' because you own it, or you can provide an update.
SELECT pr.Product, coalesce (p.person, 'US') as Owner
FROM Product pr
LEFT OUTER JOIN
(Select id_person, id_product, max(ISNULL(EndDate,getdate()+1)) as MaxAllocDate
FROM Product_Allocation a
WHERE Enddate > getdate()
group by id_person, id_product
having max(ISNULL(EndDate, getdate()+1)) =
(select max(isnull(Enddate, getdate()+1))
from product_allocation where id_product = a.id_Product)
) pa on pr.id_product = pa.id_product
LEFT OUTER JOIN person p on pa.id_person = p.id_person
The subquery will give you the max end date by product and person. since we need the subquery to return the person, you would possibly get multiple id_person records for each product if you have multiple allocations that haven't expired. The "having" clause will use the already aggregated end date to match to the max end date by product without the person, so you will get only the "most future" allocation end date. Since the product allocation is joined to the person, and they are left joined to the product table, if there are no unexpired or future allocations, or there are no allocations at all, then you will get 'US' as your owner. you can always add in another table join directly from product if your "company" is somewhere else, and substitute that for 'US'.
I don't have a data set to work off of that exactly duplicates this, so I can't test it, but I did test the having process and it functioned correctly.
if there are other assumption like, only one allocation at a time, etc, this could be simplified. Also you could work this through a memory table with only current and future allocations by product, but I believe this should work. You may need to adjust the 'getdate()' if you are working off date only not date time. If that's the case then use cast(convert(varchar(10), getdate(), 101) as datetime) and return only the date portion of the getdate function.
Hope this helps you out

Resources