I have query such as
select * from batteries as b ORDER BY inserted_at desc
which gives me data such as
and I have an query such as
select voltage, datetime, battery_id from battery_readings ORDER BY inserted_at desc limit 1
which returns data as
I want to combine both 2 above queries, so in one go, I can have each battery details as well as its last added voltage and datetime from battery_readings.
Postgres has a very useful syntax for this, called DISTINCT ON. This is different from plain DISTINCT in that it keeps only the first row of each set, defined by the sort order. In your case, it would be something like this:
SELECT DISTINCT ON (b.id)
b.id,
b.name,
b.source_url,
b.active,
b.user_id,
b.inserted_at,
b.updated_at,
v.voltage,
v.datetime
FROM battery b
JOIN battery_voltage v ON (b.id = v.battery_id)
ORDER BY b.id, v.datetime desc;
I think that widowing will make what you expected.
Assuming two tables
create table battery (id int, name text);
create table bat_volt(measure_time int, battery_id int, val int);
One of the possible queries is like this:
with latest as (select battery_id, max(measure_time) over (partition by battery_id) from bat_volt)
select * from battery b join bat_volt bv on bv.battery_id=b.id where (b.id,bv.measure_time) in (select * from latest);
If you have Postgres version which supports lateral, it might also make sense to try it out (in case there are way more values than batteries, it could have better performance).
select * from battery b
join bat_volt bv on bv.battery_id=b.id
join lateral
(select battery_id, max(measure_time) over (partition by battery_id) from bat_volt bbv
where bbv.battery_id = b.id limit 1) lbb on (lbb.max = bv.measure_time AND lbb.battery_id = b.id);
I'm working on ssrs reports. I was able to see the data or result of my stored procedure.unfortunatesly, when used the same as my dataset for report I was unable to see the data instead i'm getting 0 records.what might be the reasons ?My reports structure will be as like below image :
My current result :
Below is my procedure :
ALTER Proc [dbo].[SP_Get_CIPPSubjectMarks_New_HTSTEST] -
-7,'1,17,8','2537,2555,2558,2568'
(
#ReportId int=7,
#SubjectId varchar(200),
#SectionId varchar(200)
)
AS
BEGIN
Create table #temp (Name Varchar(500),Class varchar(50),Section
Varchar(20),enrollno varchar(500),SubjectName varchar(500),TermName
varchar(500),TestName varchar(500),TestGroupName varchar(500),Weightage
int,IsWeight bit,Marks varchar(20),MaxMarks int,IsAbsent bit,SubjectOrder
Varchar(200))
Insert into
#temp(Name,Class,Section,enrollNo,SubjectName,
TermName,TestName,TestGroupName,Weightage,IsWeight,Marks,
MaxMarks,IsAbsent,SubjectOrder)
SELECT DISTINCT CONCAT(d.name,' ',d.surname),cls.Value,sec.Value,
e.enroll_no,
CASE WHEN ISNULL(cxs.subject_alias,'')='' THEN CASE WHEN rtv.value='Second
Language' then '2ND LANGUAGE:' + b.Name WHEN
rtv.value='Third Language' THEN '3rd Language:'+b.name else b.name end
ELSE cxs.subject_alias end as SubjectName,
z.str_termname,c.str_termtestname,i.str_testgroupname,
i.str_testweightage,i.is_weighted_average,a.marks,max_marks,a.is_absent,
CASE WHEN rtv.value='Second Language' THEN 'Second Language' WHEN
rtv.Value='Third Language' THEN 'Third Language' When
ISNULL(cxs.subject_alias,'')='' THEN b.Name
ELSE cxs.subject_alias end as SubOrder
FROM marks_entry_HTS a JOIN subject b ON a.fk_subject_id=b.Id and a.marks
is not null
LEFT JOIN subjectCategory_HTS l ON l.Id= b.subject_categoryID
JOIN class_term_test_mapping_HTS c ON a.fk_class_term_test_mapping_id=c.id
-- added by me
JOIN class_term_test_category_HTS ctc on c.fk_termcategoryid = ctc.id
JOIN reference_type_value rtv ON rtv.id=a.fk_subject_type_id
-- close
JOIN Term_Test_Subject_AssessmentType_HTS m ON m.fk_term_testID=c.id and
m.fk_SubjectID=b.Id
JOIN class_report_types_mapping_test_HTS k ON
k.fk_class_term_test_mapping_id=c.Id
JOIN class_term_mapping_HTS z ON z.id=k.fk_class_term_mapping_id
JOIN Term_Test_Testgroup_aggregate_HTS i ON
i.Id=c.fk_testgroup_aggregateID
JOIN TestGroup_HTS j on j.Id=i.fk_TestGroupID
JOIN student d ON a.fk_student_id=d.Id JOIN student_enroll_no e ON
e.fk_student_id=d.id and IsNULL(e.is_deleted,0)=0
JOIN student_academic f on f.fk_student_enroll_no_id=e.id and
f.fk_academic_year_id=c.fk_academic_year_id
JOIN reference_type_value cls on cls.Id=f.fk_class_id
LEFT JOIN reference_type_value sec ON sec.Id=f.fk_section_id
LEFT JOIN max_marks_entry_HTS h on h.id=a.fk_max_marks_entry_id
join class_xref_subjects cxs ON h.fk_subject_id=cxs.fk_subject_id and
cxs.fk_subject_type_id=h.fk_subject_type_id and
IsNull(cxs.is_deleted,0)=0
and cxs.fk_class_id=h.fk_class_id and
cxs.fk_academic_year_campus_id=h.fk_academic_year_campus_id and
cxs.fk_curriculum_segment_id=h.fk_curriculum_segment_id
where k.fk_class_report_types_mapping_id=#ReportId
and h.fk_section_id in (select * from SplitStringByChar(#SectionId,','))
and a.fk_subject_id in (select * from SplitStringByChar(#SubjectId,','))
select Name,Class,Section,enrollNo,SubjectName,TermName,
TestGroupName as TestName,
Case WHEN IsWeight=1 THEN Round(Cast(((avg(CAST(Marks as
float)/cast(MaxMarks as float)))*Weightage) as decimal(10,0)),0)
else Round(Cast(((cast(max(Marks) as float)/cast(max(MaxMarks) as
float))*Weightage) as decimal(10,0)),0) ENd as Marks ,
SubjectOrder ,sum(maxmarks) as maxmarksare INTO #temp1 from #temp
GROUP BY Name,Class,Section,enrollNo,SubjectName,
TermName,SubjectOrder,IsWeight,Weightage,TestGroupName
Insert into #temp
(Name,Class,Section,enrollNo,SubjectName,
TermName,TestName,Marks,SubjectOrder)
select
Name,Class,Section,enrollNo,SubjectName,TermName,'Total',
SUM(Marks),SubjectOrder from #temp1
GROUP BY Name,Class,Section,enrollNo,SubjectName,TermName,SubjectOrder
Insert into #temp
(Name,Class,SubjectName,Section,enrollNo,TermName,TestName,Marks)
select Name,Class,'Total',Section,enrollNo,TermName,'Total
Marks',SUM(Marks)
from #temp1
GROUP BY Name,Class,Section,enrollNo,TermName
Insert into #temp
(Name,Class,SubjectName,Section,enrollNo,TermName,TestName,Marks)
select
Name,Class,'Total',Section,enrollNo,TermName,'Percentage',
SUM(Marks)*100/sum(m
axmarksare) from #temp1
GROUP BY Name,Class,Section,enrollNo,TermName
select *from #temp
drop table #temp
drop table #temp1
end
My procedure result is as like below image :
As there are a number of things that could be wrong I would do the following.
Create copy of your report
Remove the existing dataset and tablix if you want.
Create some new datasets that just get the basic data (e.g. SELECT top 10 * FROM marks_emtry_HTS). Do not use your parameters yet as we just want to test we can get basic data.
Add some tables to your report to show that the data is being returned
Add a dataset to test you are passing and parsing parameters correctly by using a dataset query like select * from SplitStringByChar(#SectionId,',') and then put tablix on your report to show the results.
Try trimming your parameter values SET #SectionId = LTRIM(RTRIM(#SectionId)) to make sure you're not handling leading or trailing space incorrectly in you split function.
If any parts do not work, run a trace on the SQL Server as you run the report and look at exactly what is being executed on the server.
I know a lot of those steps you will think might be unnecessary but take the time to do it and at least you are certain and you can exclude such basic checks from your investigation.
I need help to optmize the SQL logic in one of my functions. Please, note that I am not able to use store procedure.
Here is my table. It will be initialized using #MainTable that contains a lot of records.
DECLARE TABLE #ResultTable
(
ResultValue INT
)
These are tables that stores some parameters - they can be emty too.
DECLARE TABLE #ParameterOne (ParameterOne INT)
DECLARE TABLE #ParameterTwo (ParameterOne NVARCHAR(100))
...
DECLARE TABLE #ParameterN(ParameterN TINYINT)
Now, I need to join a lot of tables to my #MainTable in order to select from it only some of its records.
The selected records depend on the information stored in the parameters table.
So, my current solution is:
INSERT INTO ResultTable(ResultValue)
SELECT ResultValue
FROM MainTable M
INNER JOIN #MainOne MO
ON M.ID=MO.ID
....
INNER JOIN #MainN MN
ON M.IDN=MN.ID
WHERE (EXISTS (SELECT 1 FROM #ParameterOne WHERE ParameterOne=MO.ID) OR NOT EXISTS (SELECT 1 FROM #ParameterOne))
AND
...
AND
(EXISTS (SELECT 1 FROM #ParameterN WHERE ParameterN=MN.Name) OR NOT EXISTS (SELECT 1 FROM #ParameterN ))
So, the idea is to add the records only if they match the current criteria from the parameters tables.
Because I am not able to use procedure to build dynamic query I am using the WHERE clause with combinations of EXISTS and NOT EXISTS for each parameter table.
The problem is that it works slower when I am adding more and more parameters table. Is there an other way to do this without using a lot of IF/ELSE statements checking what parameter table has records - it will make the function a lot bigger and difficult for read.
And ideas and advices are welcomed.
Good question.
Try the following one:
INSERT INTO ResultTable(ResultValue)
SELECT ResultValue
FROM MainTable M
INNER JOIN (SELECT * FROM #MainOne WHERE (EXISTS (SELECT 1 FROM #ParameterOne WHERE ParameterOne=#MainOne.ID) OR NOT EXISTS (SELECT 1 FROM #ParameterOne))) MO
ON M.ID=MO.ID
....
INNER JOIN (SELECT * FROM #MainN WHERE (EXISTS (SELECT 1 FROM #ParameterN WHERE ParameterOne=#MainN.Name OR NOT EXISTS (SELECT 1 FROM #ParameterN))) MO
ON M.IDN=MN.ID
Advantages:
Result of the JOIN is more quickly, because it does not process all data (it is already filtered)
It looks more simple for adjusting
I have a stored procedure where I am trying to combine two different SELECT statements using UNION ALL, but after the query is executed only the items from the first SELECT are returned.
I wanted to get all items from both the first and second select statements.
Here is what I have:
CREATE PROCEDURE [dbo].[Report_AllActivitiesOfficesAll]
#BeginDate datetime,
#EndDate datetime
AS
SET #BeginDate = .dbo.DateOnly(#BeginDate)
SET #EndDate = .dbo.DateOnly(#EndDate)
BEGIN
SET NOCOUNT ON;
SELECT
O.OfficeId,
O.OfficeName AS Name,
AT.Description AS Activity,
SUM(A.Duration) AS [Minutes],
CAST(SUM(A.Duration) AS FLOAT) / 60 AS [Hours],
COUNT(A.ActivityId) AS Activities,
COUNT(DISTINCT A.CaseId) AS Cases,
MIN(CAST(A.Duration AS FLOAT) / 60) AS [Min Time],
MAX(CAST(A.Duration AS FLOAT) / 60) AS [Max Time],
SUM(CAST(A.Duration AS FLOAT) / 60) / COUNT(A.ActivityId) AS [Avg Time],
SUM(CAST(A.Duration AS FLOAT) / 60) AS [TotalHours]
FROM Activity A
INNER JOIN ActivityType AT ON A.ActivityTypeId = AT.ActivityTypeId
INNER JOIN ActivityEntry AE ON A.ActivityEntryId = AE.ActivityEntryId
INNER JOIN [Case] C ON A.CaseId = C.CaseId
INNER JOIN [Office] O ON AE.OfficeId = O.OfficeId
INNER JOIN [User] U ON C.CreatedByUserId = U.UserId
WHERE .dbo.DateOnly(AE.ActivityDate) BETWEEN #BeginDate AND #EndDate
GROUP BY
O.OfficeId,
O.OfficeName,
AT.Description
UNION ALL
SELECT
O.OfficeId,
O.OfficeId AS NonCaseOfficeId,
O.OfficeName AS OfficeName,
NCAT.Description AS NonCaseActivityType,
SUM(NCA.Duration) AS [Minutes],
CAST(SUM(NCA.Duration) AS FLOAT) / 60 AS [Hours],
COUNT(NCA.NonCaseActivityId) AS Activities,
MIN(CAST(NCA.Duration AS FLOAT) / 60) AS [Min Time],
MAX(CAST(NCA.Duration AS FLOAT) / 60) AS [Max Time],
SUM(CAST(NCA.Duration AS FLOAT) / 60) / COUNT(NCA.NonCaseActivityId) AS [Avg Time],
SUM(CAST(NCA.Duration AS FLOAT) / 60) AS [TotalHours]
FROM NonCaseActivity NCA
INNER JOIN NonCaseActivityType NCAT ON NCA.NonCaseActivityTypeId = NCAT.NonCaseActivityTypeId
INNER JOIN [Office] O ON NCA.OfficeId = O.OfficeId
INNER JOIN [User] U ON NCA.UserId = U.UserId
WHERE .dbo.DateOnly(NCA.ActivityDate) BETWEEN #BeginDate AND #EndDate
GROUP BY
O.OfficeId,
O.OfficeName,
NCAT.Description
END
Columns must match in data type and content to correctly and effectively use a union. You cannot change column names in the middle. If you need to know which part of the union a record came from add another column to do so. Yours do not. Officename is in the 2nd column in the first one and the third column in the second query. What is in the second column of the second query is highly likely not to be the same datatype as the second column of the first one. This is not the only mismatch but an example.
If you need a column in the second query that you don't need in the first, you must still put it in the first query. And if you need a column in the first that you don't need in the second you must put a null value in that place in the query. For example (not a complete rewrite of what you have but enough to get an idea of what I am talking about):
SELECT
O.OfficeId,
CAST(NULL as int) as NonCaseOfficeId
O.OfficeName AS Name,
AT.Description AS Activity,
COUNT(DISTINCT A.CaseId) AS Cases,
cast('Case' as varchar (10)) as recordType
FROM Activity A
INNER JOIN ActivityType AT ON A.ActivityTypeId = AT.ActivityTypeId
INNER JOIN ActivityEntry AE ON A.ActivityEntryId = AE.ActivityEntryId
INNER JOIN [Case] C ON A.CaseId = C.CaseId
INNER JOIN [Office] O ON AE.OfficeId = O.OfficeId
INNER JOIN [User] U ON C.CreatedByUserId = U.UserId
WHERE .dbo.DateOnly(AE.ActivityDate) BETWEEN #BeginDate AND #EndDate
GROUP BY
O.OfficeId,
O.OfficeName,
AT.Description
UNION ALL
SELECT
O.OfficeId,
O.OfficeId,
O.OfficeName,
NCAT.Description,
cast(NULL as int),
'NonCase'
FROM NonCaseActivity NCA
INNER JOIN NonCaseActivityType NCAT
ON NCA.NonCaseActivityTypeId = NCAT.NonCaseActivityTypeId
INNER JOIN [Office] O ON NCA.OfficeId = O.OfficeId
INNER JOIN [User] U ON NCA.UserId = U.UserId
WHERE .dbo.DateOnly(NCA.ActivityDate) BETWEEN #BeginDate AND #EndDate
Now since the query also takes the datatype from the first query, you will see that I specifically cast it to the datatype I wanted. You may need to do that on the null in the second part of the union as well just be sure that the datatypes are matching. I believe null is assumed by SQL server to be an int if you don't specify, so this is most important when you want some other data type.
Seems fine to me. Keep in mind, the column names used will come from the first query.
So if I used a query like:
SELECT 1 AS Something
UNION ALL
SELECT 2 AS SomethingElse
I'd see just results (1 and 2) under a field called Something and wouldn't see anything for a field called SomethingElse.
Perhaps that's the issue?
Try adding an extra an extra field to both queries that identifies which resultset it's pulling from.
Maybe add 'Activity' AS Source for the first query and 'Non-Case Activity' AS Source for the second query, just to make sure you're getting a clear view of what's being shown?
I have a nested select query that is returning the proper amount of rows. The query builds a recordset and compares it to a table and returns the records in the query that are not in the table.
I converted the select query to an update query. I am trying to populate the table with the rows returned from the query. When I run the update query it is returning with zero rows to update. I dont understand why because the select query is returning record and I am using the same code in the update query.
Thanks
Select Query: (This is returning several records)
Select *
From
(SELECT DISTINCT
ProductClass,SalProductClass.[Description],B.Branch,B.BranchDesc,B.Salesperson,B.Name,
CAST(0 AS FLOAT) AS Rate,'N' AS Split
FROM (SELECT SalBranch.Branch,SalBranch.[Description] AS BranchDesc,A.Salesperson,A.Name
FROM (SELECT DISTINCT
Salesperson,Name
FROM SalSalesperson
) A
CROSS JOIN SalBranch
) B
CROSS JOIN SalProductClass
) C
Left Outer Join RateComm On
RateComm.ProductClass = C.ProductClass and
RateComm.Branch = C.Branch And RateComm.Salesperson = C.Salesperson
Where RateComm.ProductClass is Null
Update Query: (This is returning zero records)
UPDATE RateComm
SET RateComm.ProductClass=C.ProductClass,RateComm.ProdClassDesc=C.ProdClassDesc,
RateComm.Branch=C.Branch,RateComm.BranchDesc=C.BranchDesc,RateComm.Salesperson=C.Salesperson,
RateComm.Name=C.Name,RateComm.Rate=C.Rate,RateComm.Split=C.Split
FROM (SELECT DISTINCT
ProductClass,SalProductClass.[Description] AS ProdClassDesc,B.Branch,B.BranchDesc,B.Salesperson,B.Name,
CAST(0 AS FLOAT) AS Rate,'N' AS Split
FROM (SELECT SalBranch.Branch,SalBranch.[Description] AS BranchDesc,A.Salesperson,A.Name
FROM (SELECT DISTINCT
Salesperson,Name
FROM SalSalesperson
) A
CROSS JOIN SalBranch
) B
CROSS JOIN SalProductClass
) C
LEFT OUTER JOIN RateComm ON C.ProductClass=RateComm.ProductClass AND
C.Salesperson=RateComm.Salesperson AND C.Branch=RateComm.Branch
WHERE RateComm.ProductClass IS NULL
It's difficult to update what doesn't exist. Have you tried an INSERT query instead?