Select With Union In SQL - sql

Why when i run the syntax in sql and the result will be double data?
The command is :
SELECT 1 AS Urut, M.Kode_Project, M.Nama_Project, M.Kode_Panel, D .Nama_Stater1, D .Tipe, D .Komponen, D .Pole, D .Amps, D .Merek, D .Qty, D .IsTitipan
FROM TransM M INNER JOIN
TransD D ON M.Kode_Project = D .Kode_Project AND M.Kode_Panel = D .Kode_Panel
WHERE M.Kode_Project = '17-0002' AND M.Kode_Panel = 'A'
UNION ALL
SELECT 2 AS Urut, M.Kode_Project, M.Nama_Project, M.Kode_Panel, M.Nama_Stater1, 'COOPER (' + SubString(Kode, 5, 100) + ')' AS Tipe,
' (' + LT + ') X ' + CONVERT(VarChar(20), Lapis) AS Komponen, '' AS Pole, '' AS Amps, ' IMPORT ' AS Merek, 1 AS Qty, 0 AS IsTitipan
FROM TransM M INNER JOIN
TransW W ON M.Kode_Project = W.Kode_Project AND M.Kode_Panel = W.Kode_Panel
WHERE LEFT(Kode, 1) <= 'B' AND M.Kode_Project = '17-0002' AND M.Kode_Panel = 'A'
What's the wrong in the command?, Thank's for who's helping.

UNION ALL will merge duplicate rows from result of two select, change
UNION ALL
to just
UNION
this will remove duplicate rows from the result

Related

How to convert Subquery to join?

Is this possible to convert the subquery by using JOIN ?
Select * from WB.Email WHERE CVALID = 'V' AND HSESID IN (
Select HSESID from WB.SDATA WHERE CSTART = 'Y' AND DPERIOD IN (select DPERIOD from WB.PERIOT WHERE CVALID = 'Y' )
AND DJOUR = (CURRENT DATE + 15 DAYS))
select e.*
from WB.Email e
join WB.SDATA s on e.HSESID = s.HSESID
join WB.PERIOT p on s.DPERIOD = p.DPERIOD
where e.CVALID = 'V'
AND s.CSTART = 'Y'
AND s.DJOUR = CURRENT_DATE + 15 DAYS
AND p.CVALID = 'Y'
Perhaps you need to do SELECT DISTINCT to remove duplicates.

could not prepare statement (1 misuse of aggregate function COUNT()) - part 2

I'm trying to run the following query:
select U1.userEmail, U1.firstname + ' ' + U1.surName as fullname
from tblUser as U1 inner join tblDriver as D on U1.userEmail= D.userEmail
inner join tblGetAsk as GA on GA.userEmail = D.userEmail
where not exists (select 1 from tblRideRating as R where R.userEmail = U1.userEmail)
and count(GA.userEmail) >= 3
But I'm getting the following error:
Error 1: could not prepare statement (1 misuse of aggregate function
COUNT())
What I'm actually want to do is: Select only users who are also a driver and have 0 records in tblRideRating, and have at least 3 records in tblGetAsk.
You can use aggregation.
Group by user and use a HAVING clause:
select U1.userEmail, U1.firstname + ' ' + U1.surName as fullname
from tblUser as U1
inner join tblDriver as D on D.userEmail= U1.userEmail
inner join tblGetAsk as GA on GA.userEmail = U1.userEmail
where not exists (select 1 from tblRideRating as R where R.userEmail = U1.userEmail)
group by U1.userEmail, U1.firstname + ' ' + U1.surName
having count(GA.userEmail) >= 3
If you have duplicate emails for each user in tblGetAsk, maybe you should change to:
having count(distinct GA.userEmail) >= 3
You could also aggregate in tblGetAsk and then join:
select U1.userEmail, U1.firstname + ' ' + U1.surName as fullname
from tblUser as U1
inner join tblDriver as D on D.userEmail= U1.userEmail
inner join (
select userEmail
from tblGetAsk
group by userEmail
having count(*) >= 3
) as GA on GA.userEmail = U1.userEmail
where not exists (select 1 from tblRideRating as R where R.userEmail = U1.userEmail)

Convert a column of Rows to only one column column in SQL Server query

I have this query in SQL Server 2012 :
select
tblplantitle.id, tblplantoproductpayment.productid
from
tblplantitle
inner join
tblplan on tblplan.plantitleid = tblplantitle.id
inner join
tblplantoproductpayment on tblplantoproductpayment.planid = tblplan.id
group by
tblplantitle.id, tblplantoproductpayment.productid
The result is like this :
id productid
1 1
1 2
1 3
1 10
2 5
2 1
3 4
3 11
but I want this result :
1 1,2,3,10
2 5,1
3 4,11
How can I get that result ?
Try this:
WITH cte as
(
select
tblplantitle.id, tblplantoproductpayment.productid
from
tblplantitle
inner join
tblplan on tblplan.plantitleid = tblplantitle.id
inner join
tblplantoproductpayment on tblplantoproductpayment.planid = tblplan.id
group by
tblplantitle.id, tblplantoproductpayment.productid
)
SELECT id, productid =
STUFF((SELECT ', ' + productid
FROM cte b
WHERE b.id= a.id
FOR XML PATH('')), 1, 2, '')
FROM cte a
GROUP BY id
Use the below query for the desired output.
SELECT tblplantitle.id
, STUFF((SELECT ', ' + CAST(tblplantoproductpayment.productid AS VARCHAR(10)) [text()]
FROM tblplantoproductpayment
WHERE tblplantoproductpayment.planid = tblplan.id
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,2,' ') List_ProductIds
FROM tblplantitle
INNER JOIN tblplan on tblplan.plantitleid = tblplantitle.id
GROUP BY tblplantitle.id

SQL query with comma separated values

I have a requirement wherein I have 3 tables
ContactInfo
idContactinfo FirstName Lastname idCOmpanyid
---------------------------------------------------
1 Blah1 Blah1 1
2 Blah2 Blah2 1
3 Blah3 Blah3 1
4 Blah4 Blah4 1
ContactRole
idcontactrole IdContactRoleName idContactInfo
------------------------------------------------------
1 1 1
2 1 2
3 1 3
4 2 4
IdContactRoleLookup
idcontactRole RoleName
----------------------------------
1 Admin
2 Secretary
I need a query that gives me a result like this
idcontactrolename Contacts
--------------------------------------------------------
Admin Blah1,Blah1;Blah2,Blah2,Blah3,Blah3
Secretary Blah4,Blah4
This is what I have till now !!
SELECT l.sValue
, SUBSTRING((
SELECT C.sLast + ',' + C.sFirst + ';'
FROM contactinfo c
inner join contactrole crole
ON crole.idcontactinfo = c.idcontactinfo
WHERE crole.idcompany = '<<blah>>'
and c.idcompany = '<<blah>>'
FOR XML PATH('')
), 1, 1000000)
FROM CONTACTROLE CR
inner join contactinfo c on
cr.idcontactinfo = c.idcontactinfo
inner join lookupdata l on cr.idlookuprole = l.idlookupdata
where c.idcompany = '<<blah>>'
SELECT
RoleName,
STUFF(
(
SELECT ';' + b.FirstName + ', ' + b.LastName
FROM ContactRole a
INNER JOIN ContactInfo b
ON a.idContactInfo = b.idContactinfo
WHERE a.IdContactRoleName = r.idcontactRole
FOR XML PATH (''))
, 1, 1, '') AS NamesList
FROM IdContactRoleLookup r
GROUP BY idcontactRole, RoleName
SQLFiddle Demo
I Would do somethng like this, where you use the ID of the main QUERY into your SUBQUERY
SELECT
l.sValue
, SUBSTRING((
SELECT C.sLast + ',' + C.sFirst + ';'
FROM contactinfo c
inner join contactrole crole
ON crole.idcontactinfo = c.idcontactinfo
WHERE c.idcompany = '<<blah>>'
AND c.idcontactrole = CR.idcontactrole
FOR XML PATH('')
), 1, 1000000)
FROM CONTACTROLE CR
inner join lookupdata l on cr.idlookuprole = l.idlookupdata
This will give you all the role for one Compagnie. If the role does'nt exist you will have a NULL value.
You can use CROSS APPLY to get the result:
select distinct l.RoleName,
left(list, len(list) -1) list
FROM CONTACTROLE CR
inner join IdContactRoleLookup l
on cr.IdContactRoleName = l.idcontactRole
cross apply
(
select C1.Lastname + ',' + C1.FirstName + ';'
from CONTACTROLE CR1
inner join contactinfo c1
on cr1.idContactInfo = c1.idContactinfo
where cr.IdContactRoleName = cr1.IdContactRoleName
FOR XML PATH('')
) t2 (list)
See SQL Fiddle with Demo

DB2 Union causes time out?

First time working with DB2. I have a stored proc that performs a union, well it trys to anyhow. The procedure times out. The select statements on either side of the union execute quickly with no issue when done individually. Why would a union do this?
Here is some sudo code for the proc, assume data types are either int or string, and they match when compared or unioned unless otherwise noted in the SQL:
DECLARE Foo CURSOR WITH RETURN FOR
Select STRIP(A.Name) as my_Name,
Case A.Number
when 2 then '(' || strip(char(A.Number)) || ')' strip(B.num)
when 3 then '(' || strip(char(A.Number)) || ')' strip(C.num)
when 4 then '(' || strip(char(A.Number)) || ')' strip(D.num)
when 5 then '(' || strip(char(A.Number)) || ')' strip(E.num)
when 6 then '(' || strip(char(A.Number)) || ')' strip(F.num)
end as my_number
FROM A
left outer join B on A.Number= 2 and A.Name = B.Name
left outer join C on A.Number= 3 and C.Name = B.Name
left outer join D on A.Number= 4 and D.Name = B.Name
left outer join E on A.Number= 5 and E.Name = B.Name
left outer join F on A.Number= 6 and F.Name = B.Name
,session.Temp_Result X
WHERE X.ID = A.ID
GROUP BY A.Number, A.Name, B.Name, C.Name, D.Name, E.Name, F.Name
for fetch only ur;
DROP TABLE Session.Temp_Result;
DECLARE GLOBAL TEMPORARY TABLE session.Temp_Result
( ID DECIMAL(18,0)
);
INSERT INTO session.Temp_Result
select X.ID
from Z, Y, X, Q
where Z.num = 6
and Z.ID = Y.ID2
and Y.GROUPA = 'ABC'
and Y.GROUPB = 'DEF'
and Y.ID = X.ID2
and X.ID = Q.ID
union
select W.ID
from Z, Y, W
where Z.num = 6
and Z.ID = Y.ID2
and Y.GROUPA = 'ABC'
and Y.GROUPB = 'DEF'
and Y.ID = W.ID2
group by ID;
OPEN C_HIERARCHIES;
Try to query using "with" statement.
DECLARE GLOBAL TEMPORARY TABLE session.Temp_Result (
ID DECIMAL(18,0))
WITH REPLACE;
INSERT INTO session.Temp_Result
(ID)
WITH Q1(Y_ID)
AS (
SELECT Y.ID
FROM Z
INNER JOIN Y ON Z.ID = Y.ID2
WHERE Z.NUM = 6 AND Y.GROUPA = 'ABC' AND Y.GROUPB = 'DEF')
SELECT X.ID
FROM X
INNER JOIN Q1 ON X.ID2 = Q1.Y_ID
WHERE EXISTS(SELECT 1 FROM Q WHERE Q.ID = X.ID)
UNION
SELECT DISTINCT W.ID
FROM W
INNER JOIN Q1 ON W.ID2 = Q1.Y_ID
If it does not help, try to use "Explain SQL" for the select statement. Maybe you should create some indexes...
My guess is that the original code is missing a join condition that is present in the pseudocode. You should rewrite the query using proper join syntax to verify the query.
In any case, if each subquery runs quickly and there is some perverse consequence of a union, can you try splitting it into two inserts:
INSERT INTO session.Temp_Result
select X.ID
from Z, Y, X, Q
where Z.num = 6
and Z.ID = Y.ID2
and Y.GROUPA = 'ABC'
and Y.GROUPB = 'DEF'
and Y.ID = X.ID2
and X.ID = Q.ID;
INSERT INTO session.Temp_Result
select W.ID
from Z, Y, W
where Z.num = 6
and Z.ID = Y.ID2
and Y.GROUPA = 'ABC'
and Y.GROUPB = 'DEF'
and Y.ID = W.ID2
group by ID;
Then you can query Temp_Result as:
select distinct id from TempResult
Removing duplicates seems unnecessary, since the data is so small, but you could also do that directly.