Transpose results of several SUM queries. Is this possible? - sql-server

I built a report based off a query that summed multiple values from a single table. It's essentially a Year To Date report, in this case, Pesticides received year to date. While the report works as a quick reference check, these totals need to be plugged (copy/pasted) into a master excel sheet that keeps a running "available balance" inventory. When I export the totals to an excel from the report, the data is not in the format it needs to be. It's horizontal instead of vertical. I can copy the data, paste it to Excel, transpose it and then copy/paste the data to where it belongs,but was wondering if it could be transposed when the query outputs the totals.
I tried the crosstab method but that appears to apply to a single table, and this query displays the sums of the columns. Perhaps I did it wrong using the crosstab method, but I tried many different ways and did not get the desired result.
Here's is the SUM query
SELECT
Agnique_MMF_Recieved.[SumOfAgnique MMF],
Altosid_30_Day_Recieved.[SumOfAltosid 30 Day],
Altosid_SR-20_Recieved.[SumOfAltosid Liquid SR-20],
Altosid_Pellets_Recieved.[SumOfAltosid Pellets],
Altosid_WSP_Recieved.[SumOfAltosid WSP],
Altosid_XR_Recieved.[SumOfAltosid XR],
Altosid_XRG_Recieved.[SumOfAltosid XRG],
Aquabac_200G_Recieved.[SumOfAquabac 200G],
BVA_2_Recieved.[SumOfBVA 2 Oil],
Four_Star_BTI_Received.[SumOfFourStar BTI],
Golden_Bear_Recieved.[SumOfGolden Bear],
Metalarv_S-9_Recieved.[SumOfMetalarv S-9],
Sustain_MGB_Recieved.[SumOfSustain MGB],
Vectobac_GS_Received.[SumOfVectobac - GS],
Vectobac_12AS_Recieved.[SumOfVectobac 12AS]
FROM
Agnique_MMF_Recieved,
Altosid_30_Day_Recieved,
Altosid_Pellets_Recieved,
Altosid_SR-20_Recieved,
Altosid_WSP_Recieved,
Altosid_XR_Recieved,
Altosid_XRG_Recieved,
Aquabac_200G_Recieved,
BVA_2_Recieved,
Four_Star_BTI_Received,
Golden_Bear_Recieved,
Metalarv_S-9_Recieved,
Sustain_MGB_Recieved,
Vectobac_12AS_Recieved,
Vectobac_GS_Received;
I would like the data to end up looking like
SumofAgniqueMMF as the row header and next to it a totals column with the value from the sum.
Anyway, is this possible? Thanks!

Can I assume that each of those tables in your FROM clause are single-record tables/views with just a single SUM in them?
if so:
SELECT 'SumOfAgnique MMF' AS [Description],
Agnique_MMF_Recieved.[SumOfAgnique MMF] AS [Sum]
FROM [Agnique_MMF_Recieved]
UNION ALL
SELECT 'SumOfAltosid 30 Day' AS [Description],
Altosid_30_Day_Recieved.[SumOfAltosid 30 Day] AS [SUM]
FROM [Altosid_30_Day_Recieved]
...etc

Consider: t==> a table, f ==> a field, r ==> a result set.
select r1.s1, r2.s2 ... rn.sn
from
(
(select sum(f1) as s1 from t1) r1,
(select sum(f2) as s2 from t2) r2,
...
...
(select sum(fn) as sn from tn) rn
)

Related

how to select first rows distinct by a column name in a sub-query in sql-server?

Actually I am building a Skype like tool wherein I have to show last 10 distinct users who have logged in my web application.
I have maintained a table in sql-server where there is one field called last_active_time. So, my requirement is to sort the table by last_active_time and show all the columns of last 10 distinct users.
There is another field called WWID which uniquely identifies a user.
I am able to find the distinct WWID but not able to select the all the columns of those rows.
I am using below query for finding the distinct wwid :
select distinct(wwid) from(select top 100 * from dbo.rvpvisitors where last_active_time!='' order by last_active_time DESC) as newView;
But how do I find those distinct rows. I want to show how much time they are away fromm web apps using the diff between curr time and last active time.
I am new to sql, may be the question is naive, but struggling to get it right.
If you are using proper data types for your columns you won't need a subquery to get that result, the following query should do the trick
SELECT TOP 10
[wwid]
,MAX([last_active_time]) AS [last_active_time]
FROM [dbo].[rvpvisitors]
WHERE
[last_active_time] != ''
GROUP BY
[wwid]
ORDER BY
[last_active_time] DESC
If the column [last_active_time] is of type varchar/nvarchar (which probably is the case since you check for empty strings in the WHERE statement) you might need to use CAST or CONVERT to treat it as an actual date, and be able to use function like MIN/MAX on it.
In general I would suggest you to use proper data types for your column, if you have dates or timestamps data use the "date" or "datetime2" data types
Edit:
The query aggregates the data based on the column [wwid], and for each returns the maximum [last_active_time].
The result is then sorted and filtered.
In order to add more columns "as-is" (without aggregating them) just add them in the SELECT and GROUP BY sections.
If you need more aggregated columns add them in the SELECT with the appropriate aggregation function (MIN/MAX/SUM/etc)
I suggest you have a look at GROUP BY on W3
To know more about the "execution order" of the instruction you can have a look here
You can solve problem like this by rank ordering the results by a key and finding the last x of those items, this removes duplicates while preserving the key order.
;
WITH RankOrdered AS
(
SELECT
*,
wwidRank = ROW_NUMBER() OVER (PARTITION BY wwid ORDER BY last_active_time DESC )
FROM
dbo.rvpvisitors
where
last_active_time!=''
)
SELECT TOP(10) * FROM RankOrdered WHERE wwidRank = 1
If my understanding is right, below query will give the desired output.
You can have conditions according to your need.
select top 10 distinct wwid from dbo.rvpvisitors order by last_active_time desc

Getting top 20 rows and the rest in 21st row in an SSRS Matrix Report

I want top 20 rows from an SSRS Matrix report and rest of the rows should be aggregated in 21st row with the row name hard coded as “Others”.
I have created the SSRS Matrix Report with row grouping based on "Category_Name" and Column grouping based on "Creation_Time". Column Group "Creation_Time" is formatted to show date in "M/yyyy" format. I am aggregating the “Id_Number” as Count(Id_Number) for each grouping and I want top 20 records sorted by count(Id_Number) in highest to the lowest order or descending order.
I have set the visibility condition as showed in the image:
I have given the following expression for the row "Others"
=count(iif(RunningValue(Fields!Category_Name.Value,countdistinct,nothing)>20,Fields!Id_Number.Value,0)
But it didn't work. I got the error saying "Running functions cannot be specified as nested aggregates".
I have earlier tried using TOP N filter on SSRS Row grouping based on count(Id_Number) which gives Top 20 rows.But if we add the " group total" to the row grouping, it will give the total of all rows and not just the top 20 rows. The logic that I thought of was to subtract the total of top 20 rows from the total of all rows. But I am not able to get the total of top 20 rows.
I used basic sql query with 2 parameters, #Begin AND #End :
SELECT Category_Name, Id_Number, Creation_Date
FROM Tbl
WHERE Creation_Date BETWEEN #Begin AND #End
The desired output of this report is this:
I am getting everything as per the desired output except for the last row "Others".
Amend your sql select script to include the following:
CASE WHEN ROW_NUMBER() OVER (ORDER BY SUM(Id_Number)DESC) >20 then 'Top 20' else 'Others' End AS 'Type'
Then in your report add in another separate tablix that is filtered by "type" = "others"

SQL Get Second Record

I am looking to retrieve only the second (duplicate) record from a data set. For example in the following picture:
Inside the UnitID column there is two separate records for 105. I only want the returned data set to return the second 105 record. Additionally, I want this query to return the second record for all duplicates, not just 105.
I have tried everything I can think of, albeit I am not that experience, and I cannot figure it out. Any help would be greatly appreciated.
You need to use GROUP BY for this.
Here's an example: (I can't read your first column name, so I'm calling it JobUnitK
SELECT MAX(JobUnitK), Unit
FROM JobUnits
WHERE DispatchDate = 'oct 4, 2015'
GROUP BY Unit
HAVING COUNT(*) > 1
I'm assuming JobUnitK is your ordering/id field. If it's not, just replace MAX(JobUnitK) with MAX(FieldIOrderWith).
Use RANK function. Rank the rows OVER PARTITION BY UnitId and pick the rows with rank 2 .
For reference -
https://msdn.microsoft.com/en-IN/library/ms176102.aspx
Assuming SQL Server 2005 and up, you can use the Row_Number windowing function:
WITH DupeCalc AS (
SELECT
DupID = Row_Number() OVER (PARTITION BY UnitID, ORDER BY JobUnitKeyID),
*
FROM JobUnits
WHERE DispatchDate = '20151004'
ORDER BY UnitID Desc
)
SELECT *
FROM DupeCalc
WHERE DupID >= 2
;
This is better than a solution that uses Max(JobUnitKeyID) for multiple reasons:
There could be more than one duplicate, in which case using Min(JobUnitKeyID) in conjunction with UnitID to join back on the UnitID where the JobUnitKeyID <> MinJobUnitKeyID` is required.
Except, using Min or Max requires you to join back to the same data (which will be inherently slower).
If the ordering key you use turns out to be non-unique, you won't be able to pull the right number of rows with either one.
If the ordering key consists of multiple columns, the query using Min or Max explodes in complexity.

Join Two Dataset In One SSRS Chart Report

i Have two data sets. First one dataset shows Total counts against each person and the Second one Dataset shows SLA breached counts against respective person. As before i used two charts for for the above datasets and result will be achieved but now i want these two datasets result in just one chart. kindly tell me how to do this to achieve desired result.
Dataset 1 (Total Counts query is):
Select Count(I.Id) AS TotalId,
U.Firstname AS Username
From I
Group U.Firstname
Dataset 2 (SLA Breached query is):
Select Count(I.Id) AS BreachedId,
U.Firstname AS Username
From I
***Where I.ResolvedDate > I. ResolvedByDate***
Group U.Firstname
The highlighted query is just used in dataset 2 which shows SLA Breached counts. Rest of the query in both dataset are same. so now i don`t know how show toghether. I used union all function but it add both TotalId and BreachedId.
Thanks
AhsanMisbah
Do you want both aggregates to appear in the same query? if so change your select to
select U.Firstname AS Username, Count(I.Id) AS TotalId, nullif(SUM(case when I.ResolvedDate > I. ResolvedByDate then 1 else 0 end ),0) as Breached

How can I split a dataset between two matrix controls in SSRS 2005

In SSRS 2005, is there a way I can create two side by side tables of 6 rows each so that each table (or Matrix) has a portion of the same data set?
Here is the query I'm using for the dataset.
Select
Equipment_EquipmentID,
Equipment_Description,
Vendor,
Operator,
JobAccount_TrackingID
from
(
Select row_number() over (partition by Equipment_EquipmentID order by JobAccount_TrackingID) row,*
from
(
SELECT DISTINCT
CustomizedFieldLogEquipmentJobAccount_1.Equipment_EquipmentID,
CustomizedFieldLogEquipmentJobAccount_1.Equipment_Description,
NULL as Vendor,
NULL as Operator,
CustomizedFieldLogEquipmentJobAccount_1.JobAccount_TrackingID
FROM
CustomizedFieldLogEquipmentJobAccount AS CustomizedFieldLogEquipmentJobAccount_1 INNER JOIN CustomizedAccount ON CustomizedFieldLogEquipmentJobAccount_1.Account_AccountID = CustomizedAccount.AccountID
WHERE
(CustomizedAccount.AppliesToEquipment = 1)
AND
(CustomizedFieldLogEquipmentJobAccount_1.FieldLog_FieldLogID =#FieldLogID)
--AND
--IsRented = 0
Union
Select Distinct
Equipment_EquipmentID,
Equipment_Description,
Null as Vendior,
NULL as Operator,
fake_TrackingID
FROM
CustomizedFieldLogEquipment
cross join
(
Select 'zzz01' fake_TrackingID
union Select 'zzz02'
union Select 'zzz03'
union Select 'zzz04'
union Select 'zzz05'
union Select 'zzz06'
union Select 'zzz07'
union Select 'zzz08'
union Select 'zzz09'
union Select 'zzz10'
) a where FieldLog_FieldLogID = #FieldLogID --AND IsRented = 0
) b
) c where Row<=6
order by Equipment_EquipmentID,JobAccount_TrackingID
The TrackingiD is the column in my Matrix and I need to show a total of 6 columns weather or not there is data in there (Hence the fake TrackingIds) the query works great. But I need to be able to split the results of the query between two matrix controls in the report if the rowcount is greater than 6.
In essence I need 2 6x6 tables. The way it needs to work is strange. If the query results return more than 6 rows, the users want the rest of the records to flow over to the 2nd table. Kind of like the illustration below:
From this:
To this:
I've already gotten the two matrix controls on the form, but can't figure out how to split the dataset between two tables like that if the row count is larger than 7 or so.
Is this possible? If so how? I've done some searching, but can't figure out how to split a single recordset into two matrix controls. Any help is appreciated. I keep trying to tell the users that this is not a form printing program but a program designed to report what is in the database.
Thanks
Add a RowNumber column to your dataset.
Then add a filter to each matrix control. The first matrix should filter for rows with RowNumber between 1-6, and the second matrix would filter for 7-12.
Admittedly, this is a quick and dirty way. The report itself however is outside the intended use of SSRS, so I don't know if it's really worth worrying about how you get the matrices to split, as long as there aren't any performance issues.
This seems so limiting and inflexible. Are the users really sure they only want x number of rows, forever? If they ever change the number of rows, you're the victim who has to make changes to the report to accommodate.

Resources