SQL GROUP BY WITH DATE - sql

I am relatively new to SQL...
I am creating a summary of returned items and I would like the finished result to show the item code, the amount returned (SUM) and the reason for return. So Ideally it would be something like this:
101 - Blue Widget | 13 | Shipment Lost
101 - Blue Widget | 3 | Damaged in Transit
102 - Red Widget | 5 | Shipment Lost
So it is grouping by ITEM and RMACODE and summing the quantities
Here is a simplified version of the query I wrote for this
Select ITEM, SUM(QUANTITY), RMACODE, DATEENTERED
FROM RMAITEMS
group by ITEM, Quantity, RMACODE
I am loading this in SSRS and need DATENETERED for my report parameters to only pull records between #StartDate and #EndDate. I get en error saying DATEENTERED is invalid because it is not in the GROUP BY.
Is there a better/different way to acheive the result I am looking for?
Thanks
Andrew
I made the changes suggested by edkloczko and it appeared everything would work then, but since we removed the date from the select statement I am unable to use it in my report parameters. Here is a screenshot. I have a few ideas I will try out today but if anyone has already climbed this hill and can help me with directions I would be grateful.
Expression Needed is Absent

If you're looking to filter by date and don't actually need the date field...
SELECT ITEM, SUM(QUANTITY), RMACODE
FROM RMAITEMS
WHERE DATEENTERED>=STARTDATE AND DATEENTERED<=ENDDATE
GROUP BY ITEM, QUANTITY, RMACODE
This will give you all the records you need and makes the extra filtering step you're doing unnecessary - it will only select the records between the start and end dates.
I've run into the same issue before with our IBM DB2. As far as I know you need to specify ALL of the SELECT items in the GROUP BY statement. Unsure if this is specific to certain databases or not.

Related

Using SQL Can I get incremental changes in data from query results? Loops?

NOTE: I am not making changes to a database. I am creating a report.
The purpose of the report is to show pending orders that need to be assembled for shipment, but not until there is enough stock to fill the order. An order includes multiple inventory items, but the inventory on hand must be >= the ordered amount per each inventory item and in order by oldest date first before the order can be added to the report.
I've written this to where it pulls the orders, but I need it to loop through to the next order and carry over the quantity of inventory On Hand from the calculation prior to this order. When the calculation is < 0, I don't need to see the order.
EXAMPLE OUTPUT:
Order Date | Order No | Item No | Quantity Ordered | On Hand | Available Qty
2015-01-01 123456 555555 50 60 10
2015-01-02 555544 555555 10 10 00
Notice On Hand says 60 for Item No 555555 in the first row. This is the actual QOH, but the report needs to subtract the amount that was ordered in the previous line from my On Hand stock, and give me the remainder, or show the new available total under On Hand. When my On Hand amount can't fulfill an order, I don't want the order to appear on my report. My current report shows On Hand to be 60 in both rows, and instead of zero, like above, it just subtracts 10 from 60, as if it's my only order.
I don't know what approach to take to do this type of incremental change in a field, but I am assuming it involves a loop and a variable (If I need to add a variable, then it needs to begin with the actual Quantity on hand), ???? Could someone please assist me with a direction? My search to answer this has only left me more unsure of how to do this. I can provide the SQL, but it is rather complicated, so I am trying to keep this on a more general level.
"Looping" should be used as a last resort in SQL. You can do so using a CURSOR but they tend to run slower and require more work than standard SQL commands.
I would recommend trying to break this problem down into smaller tables using sub-queries / CTEs (Common Table Expressions). Can you create a query that shows the total on hand amounts for each item number? Now put that into a sub-query and start building on top of it.

Query Distinct on a single Column

I have a Table called SR_Audit which holds all of the updates for each ticket in our Helpdesk Ticketing system.
The table is formatted as per the below representation:
|-----------------|------------------|------------|------------|------------|
| SR_Audit_RecID | SR_Service_RecID | Audit_text | Updated_By | Last_Update|
|-----------------|------------------|------------|------------|------------|
|........PK.......|.......FK.........|
I've constructed the below query that provides me with the appropriate output that I require in the format I want it. That is to say that I'm looking to measure how many tickets each staff member completes every day for a month.
select SR_audit.updated_by, CONVERT(CHAR(10),SR_Audit.Last_Update,101) as DateOfClose, count (*) as NumberClosed
from SR_Audit
where SR_Audit.Audit_Text LIKE '%to "Completed"%' AND SR_Audit.Last_Update >= DATEADD(day, -30, GETDATE())
group by SR_audit.updated_by, CONVERT(CHAR(10),SR_Audit.Last_Update,101)
order by CONVERT(CHAR(10),SR_Audit.Last_Update,101)
However the query has one weakness which I'm looking to overcome.
A ticket can be reopened once its completed, which means that it can be completed again. This allows a staff member to artificially inflate their score by re-opening a ticket and completing it again, thus increasing their completed ticket count by one each time they do this.
The table has a field called SR_Service_RecID which is essentially the Ticket number. I want to put a condition in the query so that each ticket is only counted once regardless of how many times its completed, while still honouring the current where clause.
I've tried sub queries and a few other methods but haven't been able to get the results I'm after.
Any assistance would be appreciated.
Cheers.
Courtenay
use as
COUNT(DISTINCT(SR_Service_RecID)) as NumberClosed
Use:
COUNT(DISTINCT SR_Service_RecID) as NumberClosed

SSRS How to Compare Columns to First Column in Group

I'm trying to create what seems like should be a pretty simple matrix report and I'm hoping someone can help. I have dataset that returns sales region, Date, and sales amount. The requirement is to compare sales for the various time periods to the current date. I'm looking to get my matrix to look something like this:
CurrentSales Date2Sales CurrentVSDate2 Date3Sales CurrentVSDate3
1 1000 1500 -500 800 200
2 1200 1000 200 900 300
3 1500 1100 400 1400 100
I can get the difference from one column to the next, but I need all columns to reference the CurrentSales column. Any help would be greatly appreciated.
Currently my data set is pulling in a date, region, product and sales amount. I then have three parameters, CurrentDate, PreviousMonth, PreviousQuarter. The regions and products are my row groups and the dates are the column groups. Next I added a column inside the group with the following expression: =Sum(Fields!SalesAmount.Value)-Previous(Sum(Fields!SalesAmount.Value),"BookingDate"). I know this isn't correct because it compares the values to the previous date in the column group and I need the comparision to be to the First date in the column group.
Example:
Using Expressions you can:
=iif(Sum(Fields!SalesAmount.Value)= Previous(Sum(Fields!Date2Sales.Value)),
=iif(Sum(Fields!EndBalance.Value)=0, Nothing, Sum(Fields!EndBalance.Value)) You can also use Switch.
The easiest way to get this result would probably be in your query. Add a field to every row returned maybe called "Current Sales." Use a correlated subquery there to get the right value for comparison. Then your comparison can be as simple as =Fields!Sales.Value - Fields!CurrentSales.Value or similar.
There are some ways to do this at the report level, but they are more of a pain: my current favorite of those is to use custom code embedded in the report. Another approach is to use Aggregates of aggregates.

SQL YTD for previous years and this year

Wondering if anyone can help with the code for this.
I want to query the data and get 2 entries, one for YTD previous year and one for this year YTD.
Only way I know how to do this is as 2 separate queries with where clauses.. I would prefer to not have to run the query twice.
One column called DatePeriod and populated with 2011 YTD and 2012YTD, would be even better if I could get it to do 2011YTD, 2012YTD, 2011Total, 2012Total... though guessing this is 4 queries.
Thanks
EDIT:
In response to help clear a few things up:
This is being coded in MS SQL.
The data looks like so: (very basic example)
Date | Call_Volume
1/1/2012 | 4
What I would like is to have the Call_Volume summed up, I have queries that group it by week, and others that do it by month. I could pull all the dailies in and do this in Excel but the table has millions of rows so always best to reduce the size of my output.
I currently group by Week/Month and Year and union all so its 1 output. But that means I have 3 queries accessing the same table, large pain, very slow not efficient and that is fine but now I also need a YTD so its either 1 more query or if I could find a way to add it to the yearly query that would ideal:
So
DatePeriod | Sum_Calls
2011 Total | 40
2011 YTD | 12
2012 Total | 45
2012 YTD | 15
Hope this makes any sense.
SQL is built to do operations on rows, not columns (you select columns, of course, but aggregate operations are all on rows).
The most standard approach to this is something like:
SELECT SUM(your_table.sales), YEAR(your_table.sale_date)
FROM your_table
GROUP BY YEAR(your_table.sale_date)
Now you'll get one row for each year on record, with no limit to how many years you can process. If you're already grouping by another field, that's fine; you'll then get one row for each year in each of those groups.
Your program can then iterate over the rows and organize/render them however you like.
If you absolutely, positively must have columns instead, you'll be stuck with something like this:
SELECT SUM(IF(YEAR(date) = 2011, sales, 0)) AS total_2011,
SUM(IF(YEAR(date) = 2012, total_2012, 0)) AS total_2012
FROM your_table
If you're building the query programmatically you can add as many of those column criteria as you need, but I wouldn't count on this running very efficiently.
(These examples are written with some MySQL-specific functions. Corresponding functions exist for other engines but the syntax would be a little different.)

Is there a way to distinct more than 1 field

I need a report that has office, date and order count. I need the total count of orders per month, but only 1 order count per day.
e.g.
West 1/1/2009 1 order
West 1/1/2009 1 order
West 1/2/2009 1 order
on my report I would see
West 1/1/2009 1 order
West 1/2/2009 1 order
and my total orders would be 2.
This would be really easy with SQL, I know, but I do not have access.
Are you just looking for this?
SELECT DISTINCT Office, Date, OrderCount FROM YourTable
This would duplicate your results, but the data set is too small to know for sure if this is what you're trying to accomplish. Using the DISTINCT clause would return only unique combinations of Office, Date, and OrderCount - in this case, one line per day/office.
UPDATE: Ah - I didn't read the part where you don't have SQL access. You still have two choices:
In Crystal Reports Designer, in the "Database" menu, check the "Select Distinct Records" option at the bottom of the menu.
Edit the SQL query directly - Database menu -> Database Expert -> Under "Current Connections", click "Add new command" and type your SQL command. Modify the one I provided above to meet your needs, and it should do the trick.
You can create three groups, one for office, one for date, and one for order. Then put the fields in the day group footer and suppress the other sections. This will cause the report to show a new section for each day, but only show one row for each order. Then you can add your running total to the section. Set the running total up to sum the field you want, evaluate on change of day group and then reset on change of month (you'll need to set a formula up for this one to evaluate the month).
This should group and order the report like you are looking for and will have a running total that will run along side which will reset per month. Hope this helps.