I reviewed similar questions but could not find an answer to my specific quandry. I'm working with SQL Server 2008 (T-SQL in SQL Server Management Studio) (but much more used to Oracle and Crystal Reports).
Simplified scenario:
Table Customer
customerID (pk)...
Table InsuranceCoverage
customerID (composite pk)
line (composite pk)
insCompanyID (fk)
insPlanID (fk)
Table InsuranceCompany
insCompanyID
insCompanyName
insCompanyAddr
Table InsurancePlan
insPlanID
insPlanName
insPlanClass
I need a report that basically returns the following on one row:
A few columns from Customer
Insurance 1 - columns from InsuranceCompany and InsurancePlan tables where InsuranceCoverage.line = 1
Insurance 2 - columns from InsuranceCompany and InsurancePlan tables where InsuranceCoverage.line = 2
Insurance 3 - columns from InsuranceCompany and InsurancePlan tables where InsuranceCoverage.line = 3
I feel very stupid not being able to figure this out. One customer might have up to three insurances. This would be easy to write multiple queries for, but I've got to get it set up so it can run automatically 1x/month. I've used the same table multiple times in the same report by using aliases on the joins before, but that won't work here because of the InsuranceCoverage.line criteria, right? Is a subquery in the from clause the answer?
Something like this?
SELECT
c.CustomerID,
cov1.*,
cov2.*,
cov3.*,
insco1.insCompanyName as insCompanyName1,
insco2.insCompanyName as insCompanyName2,
insco3.insCompanyName as insCompanyName3,
etc...
FROM
Customer c
LEFT OUTER JOIN InsuranceCoverage cov1 on cov1.CustomerID = c.CustomerID AND cov1.line = 1
LEFT OUTER JOIN InsuranceCoverage cov2 on cov2.CustomerID = c.CustomerID AND cov2.line = 2
LEFT OUTER JOIN InsuranceCoverage cov3 on cov3.CustomerID = c.CustomerID AND cov3.line = 3
JOIN InsuranceCompany insco1 on insco1.insCompanyID = cov1.insCompanyID
JOIN InsuranceCompany insco2 on insco2.insCompanyID = cov2.insCompanyID
JOIN InsuranceCompany insco3 on insco3.insCompanyID = cov3.insCompanyID
JOIN InsurancePlan inspl1 on inspl1.insPlanID = cov1.insPlanID
JOIN InsurancePlan inspl2 on inspl2.insPlanID = cov2.insPlanID
JOIN InsurancePlan inspl3 on inspl3.insPlanID = cov3.insPlanID
I set up some table variables to show that this query works. You'll need to replace them with the real table and column names. I believe something like this would work for you:
DECLARE #Customer TABLE (CustomerId INT)
DECLARE #InsuranceCoverage TABLE
(
CustomerId INT
, Line INT
, InsuranceCompanyId INT
, InsurancePlanId INT
)
DECLARE #InsuranceCompany TABLE
(
Id INT
, Name VARCHAR(100)
, Addr VARCHAR(100)
)
DECLARE #InsurancePlan TABLE
(
Id INT
, Name VARCHAR(100)
, Class VARCHAR(100)
)
SELECT
C.* -- Customer colums.
-- Insurance1 columns.
, ICmp1.*
, IP1.*
-- Insurance2 columns.
, ICmp2.*
, IP2.*
-- Insurance3 columns.
, ICmp3.*
, IP3.*
FROM
#Customer C
LEFT JOIN #InsuranceCoverage ICov1
INNER JOIN #InsuranceCompany ICmp1
ON ICmp1.Id = ICov1.InsuranceCompanyId
INNER JOIN #InsurancePlan IP1
ON IP1.Id = ICov1.InsurancePlanId
ON ICov1.CustomerId = C.CustomerId
AND ICov1.Line = 1
LEFT JOIN #InsuranceCoverage ICov2
INNER JOIN #InsuranceCompany ICmp2
ON ICmp2.Id = ICov2.InsuranceCompanyId
INNER JOIN #InsurancePlan IP2
ON IP2.Id = ICov2.InsurancePlanId
ON ICov2.CustomerId = C.CustomerId
AND ICov2.Line = 2
LEFT JOIN #InsuranceCoverage ICov3
INNER JOIN #InsuranceCompany ICmp3
ON ICmp3.Id = ICov3.InsuranceCompanyId
INNER JOIN #InsurancePlan IP3
ON IP3.Id = ICov3.InsurancePlanId
ON ICov3.CustomerId = C.CustomerId
AND ICov3.Line = 3
you can do a union of 2, 3, 4 as a derived table and join 1 with that, like...
select t1.a,t1.b,t1.c, t2.d, t2.e, t2.f from customer t1,
(select fk, d as d, 0 as e, 0 as f from ic where line=1
union select fk, 0, e, 0 from ic where line=2
union select fk, 0, 0, f from ic where line=3) as t2
where t1.pk = t2. fk
something like that
edit: oh, right, if they can have no insurance then change it to a left join like ...
select t1.a,t1.b,t1.c, t2.d, t2.e, t2.f from customer t1 left join
(select fk, d as d, 0 as e, 0 as f from ic where line=1
union select fk, 0, e, 0 from ic where line=2
union select fk, 0, 0, f from ic where line=3) as t2
on t1.pk = t2.fk
... or something like that :)
Related
I have 3 tables in that 2 tables are master table and 3rd is transaction table. i need to get count from transaction table for each value in other two table without loosing rows in mater table
i need result like below
Table layout for understanding
This is the code i have tried,
select s.status_name, e.machine_group_name, qty = COALESCE(COUNT(e.id),0)
from tbl_status s
left outer JOIN tbl_transaction as e ON e.status_name = s.status_name
group by e.machine_group_name, s.status_name
This is solution i have figured:
select m.machine_group_name, s.status_name, qty = COUNT(e.id) from
tbl_machine_group as m
cross join tbl_status as s
left outer join tbl_transaction as e on e.status_name = s.status_name
and e.machine_group_name = m.machine_group_name
group by m.machine_group_name, s.status_name
order by machine_group_name
select
MC_Group_Name
,Status_Name
,count(1) as [Count of Transaction]
from
tbl_Transaction tbl_3
left join tbl_Machine_Group tbl_1
on tbl_3.MC_Group_Name = tbl_1.MC_Group_Name
left join tbl_Status tbl_2
on tbl_3.Status_Name = tbl_2.Status_Name
group by
MC_Group_Name
,Status_Name
I have joined select columns from 3 tables into a new table using the following:
SELECT A.ExternalID, A.UserDefinedXml.value('(Skin_Sheet/#Label)[1]', 'varchar(3)') AS SS, A.ServiceSiteUid, A.LastModifiedDate, A.PersonUid,
B.FirstName, B.LastName, B.PersonUid,
C.Name
FROM Patient A
INNER JOIN Person B ON B.PersonUid = A.PersonUid
INNER JOIN ListServiceSite C ON C.ServiceSiteUid = A.ServiceSiteUid
WHERE SS IS NOT NULL
ORDER By LastModifiedDate;
This all works but I'm not sure how to reference the column SS created from data extracted from the XML so I can only select the observations in which the value is "Yes" or "No". In R I would have created a new object but I'm not sure how SQL stores this new table if I don't specify what the table name is.
Side note, I did try to insert this into a new table but SQL wasn't letting me because, for some reason, the join resulted in PersonUid being duplicated.
Thank you in advance, I'm very, very new to SQL and trying to learn on the fly.
Conceptually WHERE comes before SELECT, so you need to push the query into a derived table subquery or Common Table Expression (CTE) to reference SS in a WHERE clause. EG
with q as
(
SELECT A.ExternalID, A.UserDefinedXml.value('(Skin_Sheet/#Label)[1]', 'varchar(3)') AS SS, A.ServiceSiteUid, A.LastModifiedDate, A.PersonUid,
B.FirstName, B.LastName, B.PersonUid,
C.Name
FROM Patient A
INNER JOIN Person B ON B.PersonUid = A.PersonUid
INNER JOIN ListServiceSite C ON C.ServiceSiteUid = A.ServiceSiteUid
)
SELECT *
FROM q
WHERE SS IS NOT NULL
ORDER By LastModifiedDate;
This will put your results into a temp table, and avoids the problem of having two columns with the same name:
SELECT
A.ExternalID
,SS = A.UserDefinedXml.value('(Skin_Sheet/#Label)[1]', 'varchar(3)')
,A.ServiceSiteUid
,A.LastModifiedDate
,PersonUid_A = A.PersonUid
,B.FirstName
,B.LastName
,PersonUid_B = B.PersonUid
,C.Name
INTO #TempResults
FROM Patient A
INNER JOIN Person B ON B.PersonUid = A.PersonUid
INNER JOIN ListServiceSite C ON C.ServiceSiteUid = A.ServiceSiteUid
WHERE SS IS NOT NULL
ORDER BY LastModifiedDate;
WITH KPILibHier (kpilib_code,parent_code,kpi_name, depth, iscategory)
AS ( SELECT K.kpilib_code, K.parent_code, K.kpi_name_en, K.kpi_depth, K.iscategory
FROM TPMDPERIODKPILIB K
INNER JOIN TPMDPERIODKPI PK ON PK.period_code = K.period_code
UNION ALL
SELECT A.kpilib_code, A.parent_code, A.kpi_name_en, A.kpi_depth, A.iscategory
FROM TPMDPERIODKPILIB A
INNER JOIN KPILibHier AS B ON A.kpilib_code = B.parent_code )
SELECT DISTINCT Z.kpi_name AS libname, Z.kpilib_code AS libcode,
Z.parent_code AS pcode, Z.depth, Z.iscategory, PK.target
FROM KPILibHier Z
LEFT JOIN TPMDPERIODKPILIB KPI
ON KPI.kpilib_code = Z.kpilib_code
LEFT JOIN TPMDPERIODKPI PK
ON PK.period_code = KPI.period_code
ORDER BY Z.depth, Z.kpi_name
This is my code.
I could run it in SQL Server,
But now i have to use Mariadb,
and Mariadb doesn't use "WITH AS".
So is there any other way to change this code for the same result?
As we can see, there's "INNER JOIN KPILibHier" too inside the CTE,
So I couldn't make ordinary subquery as usual.
Just moving the contents of the CTE to a derived table should provide something usable. Something like;
SELECT DISTINCT Z.kpi_name AS libname, Z.kpilib_code AS libcode,
Z.parent_code AS pcode, Z.depth, Z.iscategory, PK.target
FROM
( SELECT K.kpilib_code, K.parent_code, K.kpi_name_en AS kpi_name, K.kpi_depth AS depth, K.iscategory
FROM TPMDPERIODKPILIB K
INNER JOIN TPMDPERIODKPI PK ON PK.period_code = K.period_code
UNION ALL
SELECT A.kpilib_code, A.parent_code, A.kpi_name_en, A.kpi_depth, A.iscategory
FROM TPMDPERIODKPILIB A
) z
INNER JOIN z AS B ON A.kpilib_code = B.parent_code
LEFT JOIN TPMDPERIODKPILIB KPI
ON KPI.kpilib_code = Z.kpilib_code
LEFT JOIN TPMDPERIODKPI PK
ON PK.period_code = KPI.period_code
ORDER BY Z.depth, Z.kpi_name
SELECT b.Device_Person_ID, a.Personal_id, Date1,
CASE WHEN b.Device_Person_id IS NOT NULL THEN 'A' ELSE 'P' END as Emp_Status
FROM Emp_setting a
LEFT OUTER JOIN (SELECT device_person_id, MAX(logDateTime) AS Date1 FROM tempDeviceLogs
GROUP BY device_person_id) b
ON a.personal_id = b.device_person_id
here i joined only two tables but i need to join 3 tables to show employee details with attendance with specific date.
Required output is
employeename device_person_id designation emptype status
'dbo.persons_profile table
[pesonal_id]
,[Emp_Code]
,[Title]
,[First_name]
,[Middle_name]
,[last_name]
,[Father_Husband_Name]
,[Dob]
,[Age]
,[gender]
,[Marital_status]
,[Nationality]
,[bloodGroup]
,[perAddress]
,[PerStreet]
,[PerLocation]
,[PerCity]
,[PerPincode]
,[CorAddress]
,[CorStreet]
,[CorLocation]
,[CorCity]
,[CorPincode]
,[LandlinePhone]
,[cellNo]
,[EmailId]
,[NosofDependendants]
,[Dependendants_details]
,[Emergency_FirstName]
,[Emergency_Middle_name]
,[Emergency_Last_name]
,[Emergency_WithRelation]
,[Emergency_PhoneNo]
,[Emergency_CellNo]
,[Emergency_emailId]
,[Office_PF_ac_no]
,[ESI_ac_no]
,[JoinedDate]
,[Photofile]
,[ReportTo]
,[Brief_Notes]
,[dateofTermination]
,[termination_note]
,[Print_Priority]
,[DeviceEmployeeID]
,[LogsPermitted]
,[Machin_install_id]
,[Designation]
,[Dept]
,[Section]
,[Groups]
,[EmpWorkingTypeT]'
dbo.tempDeviceLogs table
[LogsID]
,[Device_Person_id]
,[Device_id]
,[logDateTime]
,[logVerifyMode]
,[workCodeID]
,[Machin_install_id]
,[data_loaded_dt]
,[Inout]
dbo.Emp_setting table
[Empset_id]
,[personal_id]
,[DesignationID]
,[DivisionID]
,[Emp_status]
,[Emp_TypeId]
,[Dept_Id]
,[Group_Id]
,[NDIVGRP_CODE]
you need to write to join conditions for achieving what you required.
as an example:
SELECT a.<respective>_id, d.<respective>_title, s.<respective>_id
FROM Emp_setting a
INNER JOIN persons_profile s ON a.<respective>_id = s.<respective>_id
INNER JOIN Emp_setting d ON a.<respective>_id = d.<respective>_id
INNER JOIN tempDeviceLogs b ON s.<respective>_id = b.<respective>_id
there is a column comment_id of a table called pic_alb_love which i'd like to add to the query below but i don't know how. Actually what i want to do is to count the total comment_id of the table pic_alb_love.
SELECT users_pics.wardrobe,
profile.fname,
users_pics.pic,
users_pics.u_pic_id,
users_pics.email,
users_pics.make,
users_pics.designer,
photo_comment.comment,
max_photo_comment.count_pic_id
FROM dbo.users_pics
INNER JOIN profile
ON users_pics.email = profile.email
LEFT Join (SELECT pic_id
,MAX(comment_id) max_comment_id
,COUNT(pic_id) count_pic_id
FROM photo_comment
GROUP BY pic_id
) max_photo_comment
On users_pics.u_pic_id = max_photo_comment.pic_id
LEFT Join photo_comment
On max_photo_comment.pic_id = photo_comment.pic_id
AND max_photo_comment.max_comment_id = photo_comment.comment_id
WHERE users_pics.wardrobe = MMColParam
AND users_pics.email = MMColParam2
ORDER BY u_pic_id asc
these are the various fields of the table pic_alb_love:
(comment_id,pic,love_com, wardrobe, email
,com_name,resp_email, play_count, com_stat)
LEFT JOIN (SELECT Pic
,Count(*) [CommentCount]
FROM pic_alb_love
GROUP BY Pic) c
ON c.Pic=u_pic_id
Assuming that pic_alb_love.pic is the FK on the table...
Use [CommentCount] in the select list.