I have a rather large query that I run on a particular database. What this query does is select specific columns from specific tables and dumps them into a new table. The new table is used and modified later in the query.
The problem I'm running into is, while the databases are supposedly from the same program, one database might have columns email1, email2, and email3 but the next one might only have email1. Because email1-3 are used as a part of the select statement, when one of these columns is missing, that portion fails and the table never gets created.
I'm still very much new to this so my question may be simple or silly but is there any way to save the results when a column is missing like this? I could just as easily just remove the columns that are missing from the query and run it again but I'm wondering if there is a more correct way to do this?
Example:
SELECT Customer.[Name],
Customer.AcctKey,
SUBSTRING(Customer.LastName,1,25) AS [Last Name],
SUBSTRING(Customer.FirstName,1,25) AS [First Name],
Customer.Add1 AS Address,
Customer.Add2 AS Address2,
Customer.City,
Customer.State,
Customer.Zip,
Location.Add1 AS [Ship Address],
Location.Add2 AS [Ship Address2],
Location.City AS [Ship City],
Location.State AS [Ship State],
Location.Zip AS [Ship Zip],
Customer.Phone1 AS Phone,
Customer.Phone2 AS [Alt Phone],
Customer.Phone3 AS [Cell Phone],
Customer.Phone4 AS Fax,
Customer.lblPhone1,
Customer.lblPhone2,
Customer.lblPhone3,
Customer.lblPhone4,
Customer.Terms,
Customer.[Key] AS [Account Number],
Location.Notes,
Location.TaxCode AS [Tax Item],
Location.Zone AS [Map Code],
Location.Contact,
Location.Email,
Location.Email6, --Fails because column(s) Email2-6
Location.Email5, --don't exist in this database
Location.Email4, --but they might in another
Location.Email3, --and I'd like to get the data
Location.Email2, --if they do
Location.Phone6,
Location.Phone5
INTO [01Parents]
FROM Customer
INNER JOIN Location ON Customer.[Key] = Location.[Key]
You could try the following.
DECLARE #SQL AS NVARCHAR(MAX)
SELECT
#SQL = COALESCE(#SQL, N'') + CASE WHEN #SQL IS NULL THEN c.name ELSE N', ' + c.name END
FROM
sys.columns AS c INNER JOIN sys.objects AS o
ON
c.object_id = o.object_id
WHERE
o.name = #table
ORDER BY
c.column_id
SET #SQL = N'SELECT ' + #SQL + N' INTO 01Parents FROM Customer INNER JOIN ON Customer.[Key] = Location.[Key]'
EXEC sp_executesql #sql
Related
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 have this query in a pl/pgsql function. I am using PostgreSQL 10.
FOR firstrecord IN
EXECUTE format(
'SELECT vans.id as vid, adidas.id as aid,
vans.color, adidas.color, vans.type, adidas.type
FROM shoes
FULL JOIN adidas ON shoes.id = adidas.id
FULL JOIN shoes ON shoes.id=vans.id
WHERE adidas.code = 607 and vans.code = 304 ' )
USING acode , vcode
END LOOP;
This works, but I would like to enforce a SELECT DISTINCT on vans.id AND
adidas.id.
This is the closest I got
FOR firstrecord IN
EXECUTE format(
'SELECT DISTINCT ON (adidas.id) vans.id as vid, adidas.id as aid,
vans.color, adidas.color, vans.type, adidas.type
FROM shoes
FULL JOIN adidas ON shoes.id = adidas.id
FULL JOIN shoes ON shoes.id=vans.id
WHERE adidas.code = 607 and vans.code = 304
ORDER BY adidas.id,vans.id' )
USING acode , vcode
END LOOP;
If I try to do something like SELECT DISTINCT ON (adidas.id, vans.id) the DISTINCT does not work, I get duplicates in result.
If I do SELECT DISTINCT vans.id as vid, adidas.id as aid , still the DISTINCT does not work, I get duplicates in result.
How do I fix this?
Thanks
As you're seeing now, if you use DISTINCT ON( expression1, expression2) it'll count all the combinations of the two expression as distinct, including when one is NULL as distinct from any non-NULL value. It seems like you want just one expression that takes in to account the ids from both tables. You can get this using the coalesce function, like so:
SELECT DISTINCT ON ( coalesce(adidas.id, vans.id)) vans.id as vid, adidas.id as aid,
vans.color, adidas.color, vans.type, adidas.type
FROM shoes
FULL JOIN adidas ON shoes.id = adidas.id
FULL JOIN vans ON shoes.id = vans.id
WHERE adidas.code = 607 and vans.code = 304
ORDER BY coalesce(adidas.id, vans.id)
This works in this case because if both are non-NULL, they should match one another, and if one is NULL the coalesce statement will return the non-NULL value.
I have a table MyTable that is populated by BizTalk from two outside agencies (AGC1 and AGC2) every day. I have recently run into a problem where AGC2 has been sending a blank file, so no records get updated.
I need to run a query like below, that would return
AGC1 01/28/2016
AGC2 NULL
But since I have no records for AGC2 I only get
AGC1 01/28/2016
How can I get AGC2 NULL as in the first resultset?
SELECT Agency, MAX(CONVERT(nvarchar(30), DATEENTERED, 101)), Case when MAX(CONVERT(nvarchar(30), DATEENTERED, 101)) = CONVERT(nvarchar(30), GETDATE(), 101) THEN 'True' ELSE 'False' end
FROM DBO.MYTABLE
GROUP BY AGENCY
Have another table containing:
NameTable
Name
-----
AGC1
AGC2
Then use this query:
Select n.Name, max(m.dateentered)
from MyTable m right join NameTable n
on m.Agency = n.Name
group by n.Name
A RIGHT JOIN with a table containing all agencies should do the trick. This version uses a derived table with VALUES:
SELECT
ag.Agency,
MAX(CONVERT(nvarchar(30), mt.DATEENTERED, 101)),
Case when MAX(CONVERT(nvarchar(30), mt.DATEENTERED, 101)) = CONVERT(nvarchar(30), GETDATE(), 101) THEN 'True' ELSE 'False' end
FROM
DBO.MYTABLE AS mt
RIGHT JOIN ( VALUES('AGC1'),('AGC2') ) AS ag(Agency) ON
ag.Agency=mt.Agency
GROUP BY
ag.AGENCY
I often use queries like:
SELECT *
FROM ThisTable
OUTER APPLY (SELECT (SELECT SomeField + ' ' AS [data()]
FROM SomeTable
WHERE SomeTable.ID = ThisTable.ID
FOR XML PATH ('')) AS ConcatenatedSomeField) A
I often want to get multiple concatenated concatenated fields from this table, instead of just one. I could logically do this:
SELECT *
FROM ThisTable
OUTER APPLY (SELECT (SELECT SomeField + ' ' AS [data()]
FROM SomeTable
WHERE SomeTable.ID = ThisTable.ID
FOR XML PATH ('')) AS ConcatenatedSomeField) A
OUTER APPLY (SELECT (SELECT SomeField2 + ' ' AS [data()]
FROM SomeTable
WHERE SomeTable.ID = ThisTable.ID
FOR XML PATH ('')) AS ConcatenatedSomeField2) B
OUTER APPLY (SELECT (SELECT SomeField3 + ' ' AS [data()]
FROM SomeTable
WHERE SomeTable.ID = ThisTable.ID
FOR XML PATH ('')) AS ConcatenatedSomeField3) C
But it looks crappy and error prone when anything needs to be updated; also SomeTable is often a long list of joined tables so it could also have performance implications getting the same tables over and over.
Is there a better way to do this?
Thanks.
You could do something like this. Instead of immediately sending the XML value to a string, this query uses the TYPE keyword to return an xml type object which can then be queried. The three query functions search the xml object for all instances of the Somefield element and return a new xml object containing just those values. Then the value function strips out the xml tags surrounding the values and passes them into a varchar(max)
SELECT ThisTable.ID
,[A].query('/Somefield').value('/', 'varchar(max)') AS [SomeField_Combined]
,[A].query('/Somefield2').value('/', 'varchar(max)') AS [SomeField2_Combined]
,[A].query('/Somefield3').value('/', 'varchar(max)') AS [SomeField3_Combined]
FROM ThisTable
OUTER APPLY (
SELECT (
SELECT SomeField + ' ' AS [SomeField]
,SomeField2 + ' ' AS [SomeField2]
,SomeField3 + ' ' AS [SomeField3]
FROM SomeTable
WHERE SomeTable.ID = ThisTable.ID
FOR
XML PATH('')
,TYPE
) AS [A]
) [A]
You can create a CLR User-Defined Aggregate Function that does the concatenation for you.
Your code would then look like this instead.
select S.ID,
dbo.Concat(S.SomeField1),
dbo.Concat(S.SomeField2),
dbo.Concat(S.SomeField3)
from SomeTable as S
group by S.ID
This is the same answer as I gave here: https://dba.stackexchange.com/questions/125771/multiple-column-concatenation/
The OP of that question referenced the answer given here. You can see below that sometimes the simplest answer can be the best. If SomeTable is multiple tables then I would go ahead and put it into a CTE to avoid having the same complex code multiple times.
I ran a few tests using a little over 6 mil rows. With an index on the ID column.
Here is what I came up with.
Your initial query:
SELECT * FROM (
SELECT t.id,
stuff([M].query('/name').value('/', 'varchar(max)'),1,1,'') AS [SomeField_Combined1],
stuff([M].query('/car').value('/', 'varchar(max)'),1,1,'') AS [SomeField_Combined2]
FROM dbo.test t
OUTER APPLY(SELECT (
SELECT id, ','+name AS name
,','+car AS car
FROM test WHERE test.id=t.id
FOR XML PATH('') ,type)
AS M)
M ) S
GROUP BY id, SomeField_Combined1, SomeField_Combined2
This one ran for ~23 minutes.
I ran this version which is the version I first learned. In some ways it seems like it should take longer but it doesn't.
SELECT test.id,
STUFF((SELECT ', ' + name
FROM test ThisTable
WHERE test.id = ThisTable.id
FOR XML PATH ('')),1,2,'') AS ConcatenatedSomeField,
STUFF((SELECT ', ' + car
FROM test ThisTable
WHERE test.id = ThisTable.id
FOR XML PATH ('')),1,2,'') AS ConcatenatedSomeField2
FROM test
GROUP BY id
This version ran in just over 2 minutes.
I'm trying to produce a Winforms report in my .NET application. Our users want to know for a specific welder what type of welds they have done between two dates. The users also need proof that this weld has been completed. The front end is straightforward but I'm struggling on how to get the data.
I have the following SQL query in a stored procedure:
INPUT parameters: #WelderNo INT, #StartDate DATETIME, #EndDate DATETIME
SELECT DISTINCT wi.wi_wpsnumbers
FROM wi_weld_instance wi
INNER JOIN wlds_weld_section ws ON wi.weldinstanceid = ws.weldinstanceid
INNER JOIN erd_employee_resourcedetails e ON e.employeeid = ws.employeeid
WHERE (wi.wi_completiondate Between #StartDate AND #EndDate)
AND e.erd_welderno in (#WelderNo)
Now I want to get some other information on each distinct wi_wpsnumbers that was returned. This is the proof that the weld has been completed. The query would look something like this:
Input parameters: #WelderNo INT, #StartDate DATETIME, #EndDate DATETIME, #wi_wpsnumber NVARCHAR(MAX)
SELECT TOP(1) e.fabemployeename,
erd_welderno,
(pm.PM_Number),
(mm.mm_assemblymark),
(wd.wd_number),
(wd.wd_length),
(wi.wi_completiondate)
FROM wi_weld_instance wi
INNER JOIN wlds_weld_section ws ON wi.weldinstanceid = ws.weldinstanceid
INNER JOIN erd_employee_resourcedetails e ON e.employeeid = ws.employeeid
INNER JOIN wd_weld_definition wd ON wd.welddefinitionid = wi.welddefinitionid
INNER JOIN pm_project_map pm ON pm.projectmapid = wd.projectid
INNER JOIN mm_mark_map mm ON wd.assemblyid = mm.markmapid
WHERE (wi.wi_completiondate Between #StartDate AND #EndDate)
AND e.erd_welderno in (#WelderNo) AND wi.wi_wpsnumbers = #wi_wpsnumber
How can I create a stored procedure that returns a table with the combination of both these queries? I can't combine the queries as the distinct will not work and return multiple wi_wpsnumbers the same. I was looking at temp tables but then I don't understand how to insert both the results of these queries into the same row. Thanks for your help
Link to database diagram: http://i1215.photobucket.com/albums/cc510/gazamatazzer/DatabaseDiagram.jpg
You can return two resultsets from an SP.
Just call two SELECTs and use NextResult in the client code to retrieve the second resultset after you have read the first one.
select x.*, y.* from
(select * from xtable) x, (select * from ytable) y
Where x.* gives you all from xtable and y.* gives all from ytable