SELECTING from same field in 2 column - sql

I want to create a report that appears from the same field in two columns
example :
receipt id infotype information
-----------------------------------------------
1 phone number 123
1 comment no comment
2 phone number 12346
2 any comment price is high
Result :
receipt id phone number comment
----------------------------------------------
1 123 no comment
2 12346 price is high
I use this code but the result is not same I need:
SELECT
RETAILTRANSACTIONINFOCODETRANS.TRANSDATE AS "Date" ,
RETAILTRANSACTIONTABLE.RECEIPTID AS "Receipt number" ,
RETAILTRANSACTIONSALESTRANS.staff As "Staff" ,
RETAILTRANSACTIONTABLE.NETAMOUNT AS "Total" ,
RETAILTRANSACTIONINFOCODETRANS.INFOCODEID AS " Type " ,
RETAILTRANSACTIONINFOCODETRANS.INFORMATION,
MAX(CASE WHEN RETAILTRANSACTIONINFOCODETRANS.INFOCODEID = 'Phone Numb' THEN information END) AS phonenumber,
MAX(CASE WHEN RETAILTRANSACTIONINFOCODETRANS.INFOCODEID LIKE '%Any Commen%' THEN information END) AS comment
FROM
RETAILTRANSACTIONTABLE
INNER JOIN
RETAILTRANSACTIONINFOCODETRANS ON RETAILTRANSACTIONINFOCODETRANS.TRANSACTIONID = RETAILTRANSACTIONTABLE.TRANSACTIONID
INNER JOIN
RETAILTRANSACTIONSALESTRANS ON RETAILTRANSACTIONSALESTRANS.TRANSACTIONID = RETAILTRANSACTIONINFOCODETRANS.TRANSACTIONID
GROUP BY
GROUPING SETS ((RETAILTRANSACTIONINFOCODETRANS.TRANSDATE,
RETAILTRANSACTIONTABLE.RECEIPTID,
RETAILTRANSACTIONSALESTRANS.staff,
RETAILTRANSACTIONTABLE.NETAMOUNT,
RETAILTRANSACTIONINFOCODETRANS.INFORMATION,
RETAILTRANSACTIONINFOCODETRANS.INFOCODEID ),())

You can use conditional aggregation
select receiptid,
max(case when infotype='phone number' then information end) as phonenumber,
max(case when infotype like '%comment%' then information end) as comment
from tablename
group by receiptid

select * from
(
SELECT [receipt id]
,[infotype]
,[information]
FROM [test].[dbo].[report]) as x
pivot
(
max([information])
for [infotype] in([phone],[comment]) )as pvt

Related

Turning rows into columns with a condition? SQL Server

I have table1 with the following data for example:
PersonID Description StartDate EndDate
---------------------------------------------------------
ABC Do not call 2000-05-10 NULL
ABC Do not solicit 2005-10-15 NULL
XYZ Do not email 2010-12-20 NULL
FGH Do not contact 2020-10-11 2021-12-11
I am trying to turn each of the values in the Description column to be its own column and to show a "1" if the PersonID has this value in their row and as long as the EndDate is NULL for that Description, otherwise show "0" for example:
PersonID Do Not Call Do Not Solicit Do not email Do not contact
---------------------------------------------------------------------------------------------
ABC 1 1 0 0
XYZ 0 0 1 0
FGH 0 0 0 0
I've tried using PIVOT for example:
SELECT PersonID, [Do not call], [Do not call solicit], [Do not email], [Do not contact]
from table1 as SourceTable
PIVOT
(
COUNT(Description)
for Description IN ([Do not call], [Do not call solicit], [Do not email], [Do not contact])
) as PivotTable
But this gives me multiple rows of the same PersonID, whereas I just want one unique PersonID row, and then just value of 1 or 0 in the remaining columns of "Do not call", "Do not solicit", etc...
Also with my query, I am unable to check whether the row has an EndDate or not, because if it does have an EndDate value, then I want it to display 0 instead of 1.
Rather than a pivot I would choose to use conditional aggregation for this. Also, I would suggest not putting spaces in your column names as it just makes it harder to work with and provides no actual benefit.
select PersonID
, DoNotCall = MAX(case when Description = 'Do Not Call' then 1 end)
, DoNotSolicit = MAX(case when Description = 'Do Not Solicit' then 1 end)
, DoNotEmail = MAX(case when Description = 'Do not email' then 1 end)
, DoNotContact = MAX(case when Description = 'Do not contact' then 1 end)
from table1
group by PersonID
group by PersonID

Selecting multiple rows of a column in a SQL Server query

I have a table, let's call it Case the case table contains basic information about a case, such as the CaseNumber and the CaseOwner.
In a separate table, CaseDetails a number of phone numbers associated with a particular case are stored. The Type column within CaseDetails represents the type of phone number e.g. Home, mobile or work. These two tables link on CaseNumber.
More clearly:
Case
CaseNumber CaseOwner
------------------------
1 Bob
2 Jim
3 Gary
CaseDetails
CaseNumber Detail Type
----------------------------------
1 0123456789 1
1 1111111111 2
2 2222222222 1
1 0101001011 3
2 1234123412 2
3 0000011111 1
3 1231231231 2
I want to be able to write a query that can pull back the basic details of a case, as well as ALL of the associated phone numbers.
In my head I imagined the query to go something like the following
Select
CaseNumber, CaseOwner,
Detail where Type = 1, Detail where Type = 2, Detail where Type = 3
From
Case
Join
CaseDetails on Case.CaseNumber = CaseDetails.CaseNumber
That way each individual Detail could be extracted from the CaseDetails table using the type column. However this is syntactically incorrect and won't execute.
How exactly would I construct a query to extract this information? I can't seem to find the information on this on Google as I'm not sure what to search for.
The whole point of this is so that I can find all of the associated numbers for a particular case and store them in one location.
This is what I want the final output to look like
CaseNumber CaseOwner Detail1 Detail2 Detail3
-------------------------------------------------------------------
1 Bob 0123456789 1111111111 0000011111
You can try below using CASE WHEN expression
Select a.CaseNumber, CaseOwner, max(case when Type = 1 then detail end) as as detail1, max(case when Type = 2 then detail end) as detail2, max(case when Type = 3 then detail end) as detail3
From Case a
Join CaseDetails b on a.CaseNumber = b.CaseNumber
group by a.CaseNumber, CaseOwner
OR you can use PIVOT
with cte as
(
Select a.CaseNumber, CaseOwner, type, detail
From Case a
Join CaseDetails b on a.CaseNumber = b.CaseNumber
group by a.CaseNumber, CaseOwner
)
select casenumber, caseowner,pv.*
from cte pivot(max(detail) for type in (1,2,3)) as pv
You can use conditional aggregation:
Select c.CaseNumber, c.CaseOwner,
max(case when cd.type = 1 then cd.Detail end) as detail_1,
max(case when cd.type = 2 then cd.Detail end) as detail_2,
max(case when cd.type = 3 then cd.Detail end) as detail_3
From Case c Join
CaseDetails cd
on c.CaseNumber = cd.CaseNumber
group by c.CaseNumber, c.CaseOwner;
EDIT:
You can also do this using outer apply:
select c.*, cd.*
from case c outer apply
(select max(case when cd.type = 1 then cd.Detail end) as detail_1,
max(case when cd.type = 2 then cd.Detail end) as detail_2,
max(case when cd.type = 3 then cd.Detail end) as detail_3
from CaseDetails cd
where c.CaseNumber = cd.CaseNumber
) cd;
use pivot
select CaseNumber,CaseOwner,
[1] as detail1,
[2] as detail2 ,
[3] as detail3
from
(select c1.CaseNumber,c1.CaseOwner,c2.Detail,c2.Type
From Case c1
Join CaseDetails c2
on c1.CaseNumber = c2.CaseNumber
) src
PIVOT
(
max(Detail) for Type in ([1],[2],[3])
) pvt

SQL query for count all(unknown, known), unknown, known customer, identify uniquely by Phone Mac address

Table 1(Customer Table)
Id, CustomerId, IsKnownCustomer,phonemacaddress
1, NULL 0 00:9a:34:cf:a4
2, 004024 1 00:6f:64:cf:a0:93
3, 004024 1 00:6f:64:cf:a0:93
4, 004003 1 2c:0e:3d:15:12:43
6, NULL 0 2c:0e:3d:15:125
7, 004003 1 34:f3:9a:ee:53:a9
8, 004023 1 38:0B:40:DC:BA:3A
9, NULL 0 4c:66:41:11:26:16
This is the table, and data is required for all customer, unknown customer and known customer.
output like: uniquely find the records by phonemacaddress.
count Customer,| customer type|
7 all
3 unknown customer
4 known customer
You could use union and count
select count(*), 'all'
from customer
union
select count(*), 'unknown customer'
from customer
where isKnowCustomer = 0
union
select count(*), 'known customer'
from customer
where isKnowCustomer = 1
I would just put this in one row:
select count(*) as all,
sum(IsKnownCustomer) as known,
sum(1 - IsKnownCustomer) as unknown
from t;
I'm not sure why you would want three rows rather than three columns.
If you do, you can do:
select (case when isKnownCustomer = 0 then 'Unknown'
when isKnownCustomer = 1 then 'Known'
else 'All'
end) as which, count(*)
from t
group by grouping sets ( (IsKnownCustomer), () )
Below SQL would help you.
SELECT
SUM(CASE WHEN Isknown = 1 THEN 1 ELSE 0 END) AS 'Known Customer',
SUM(CASE WHEN Isknown = 0 THEN 1 ELSE 0 END) AS 'Unknown Customer',
COUNT(*) AS 'All'
FROM YourTable
You can aggregate the table with one scan, then use UNPIVOT.
SELECT [count customer], [customer type]
FROM ( --aggregations will be placed side-by-side
SELECT COUNT(*) [all]
,COUNT(CASE WHEN IsKnownCustomer = 0 THEN 1 END) [unknown customer]
,COUNT(CASE WHEN IsKnownCustomer = 1 THEN 1 END) [known customer]
FROM CustomerTable
) AS dT
UNPIVOT( --unpivot, will separate aggregations by row
[count customer] FOR [customer type] IN ([all], [unknown customer], [known customer])
) AS unp
Creates Output:
count customer customer type
9 all
3 unknown customer
6 known customer
Here is the full code in SQL fiddle: http://sqlfiddle.com/#!6/54e54/2/0

SQL Server : split a column with varied data into 3 specific columns grouped by ID

Using SQL Server, I'm trying to split information shared in one column into three based on the number of IDs. Ideally I'd have distinct IDs at the end.
There can be from 1-3 rows per PersonID depending on the information in the contact column.
If a personID appears more than once I'd like to have the data split into two columns, one for phone and one for email.
I'd need to check that the data contained an "#" symbol for it to be put into the Email column, and the rest put into Phone or Alt Phone.
It's pretty hard to explain so if you need any more information please comment.
Hopefully the example below will help:
PersonID Name Contact
----------------------------------------
1 Chen 212747
1 Chen Chen#test.com
2 Pudge 18191
2 Pudge 18182222
2 Pudge Pudge#test.com
3 Riki Riki#test.com
3 Riki 19192
4 Lina 18424
I want to convert this into :
PersonID Name Phone Alt Phone Email
--------------------------------------------------------
1 Chen 212747 NULL Chen#test.com
2 Pudge 18191 18182222 Pudge#test.com
3 Riki 19192 NULL Riki#test.com
4 Lina 18424 NULL NULL
declare #Table AS TABLE
(
PersonID INT ,
Name VARCHAR(100),
Contact VARCHAR(100)
)
INSERT #Table
( PersonID, Name, Contact)
VALUES
(1 ,'Chen','212747'),
(1 ,'Chen','Chen#test.com'),
(2 ,'Pudge','18191'),
(2 ,'Pudge','18182222'),
(2 ,'Pudge','Pudge#test.com'),
(3 ,'Riki','Riki#test.com'),
(3 ,'Riki','19192'),
(4 ,'Lina','18424')
SELECT
xQ.PersonID,
xQ.Name,
MAX(CASE WHEN xQ.IsEmail = 0 AND xQ.RowNumberPhone = 1 THEN xQ.Contact ELSE NULL END) AS Phone,
MAX(CASE WHEN xQ.IsEmail = 0 AND xQ.RowNumberPhone = 2 THEN xQ.Contact ELSE NULL END) AS [Alt Phone],
MAX(CASE WHEN xQ.IsEmail = 1 AND xQ.RowNumberEmail = 1 THEN xQ.Contact ELSE NULL END) AS Email
FROM
(
SELECT *
,CASE WHEN PATINDEX('%#%',T.Contact)>0 THEN 1 ELSE 0 END AS IsEmail
,RANK() OVER(PARTITION BY T.PersonID, CASE WHEN PATINDEX('%#%',T.Contact)=0 THEN 1 ELSE 0 END ORDER BY T.Contact) AS RowNumberPhone
,RANK() OVER(PARTITION BY T.PersonID, CASE WHEN PATINDEX('%#%',T.Contact)>0 THEN 1 ELSE 0 END ORDER BY T.Contact) AS RowNumberEmail
FROM #Table AS T
)AS xQ
GROUP BY
xQ.PersonID,
xQ.Name
ORDER BY xQ.PersonID
You can do it using subqueries
declare #tbl table(PersonID int,Name varchar(50),Contact varchar(100))
insert into #tbl
select 1,'Chen','212747' union
select 1,'Chen','Chen#test.com' union
select 2,'Pudge','18191' union
select 2,'Pudge','18182222' union
select 2,'Pudge','Pudge#test.com' union
select 3,'Riki','Riki#test.com' union
select 3,'Riki','19192' union
select 4,'Lina','18424'
SELECT DISTINCT
M.PersonID
,M.Name
,(SELECT TOP 1 Contact FROM #tbl WHERE PersonID = M.PersonID AND Contact NOT LIKE '%#%' ORDER BY Contact) AS Phone
,(SELECT TOP 1 Contact FROM #tbl WHERE PersonID = M.PersonID AND Contact NOT LIKE '%#%'
AND Contact NOT IN (SELECT TOP 1 Contact FROM #tbl WHERE PersonID = M.PersonID AND Contact NOT LIKE '%#%' ORDER BY Contact)) AS AltPhone
,(SELECT TOP 1 Contact FROM #tbl WHERE PersonID = M.PersonID AND Contact LIKE '%#%') AS Email
FROM #tbl M
Output
1 Chen 212747 NULL Chen#test.com
2 Pudge 18182222 18191 Pudge#test.com
3 Riki 19192 NULL Riki#test.com
4 Lina 18424 NULL NULL
Using row number and group by person id you can achieve the same by below query.
Select PersonID, max(Name) name,
max(case when rn=1 and contact not like '%#%' then contact end) phone,
max(case when rn=2 and contact not like '%#%' then contact end) Alt_Phone,
max(case when contact like '%#%' then contact end) mailid
from(select t.*, row_number() over(partition by personid order by contact) as rn from table t) as t2
group by PersonID

Count records in same column with and without parameter

I am having some trouble with a query and was hoping someone could help. I have tried searching for a solution, but can't seem to find a similar scenario with my search terms.
Here is what I am looking for:
I have a table with three columns and need to return the values in the first column, and two counts of the values in the second column. One count is based on a parameter and the other is the total count. Ideally, I would only like to return the values in column one that have equal counts.
For example:
Part Number | Make ID
ABC123 | 1<br>
ABC123 | 1<br>
ABC123 | 3<br>
DEF456 | 1<br>
DEF456 | 1
Part Number | Count of Apps Where Make ID = 1| Count of Total Apps
ABC123 | 2 | 3
DEF456 | 2 | 2
The query I have so far will return the total count of apps for part numbers that have the parameter value, but I need it to return both counts:
SELECT apps.part#,
COUNT(DISTINCT application#)apps
FROM [mytable] AS apps
INNER JOIN (SELECT part#
FROM [mytable]
WHERE make = '1') AS sz
ON sz.part# = apps.part#
GROUP BY apps.part#
ORDER BY 1
Any help is greatly appreciated!
Thanks, everyone! I received several correct answers, and selected the one that was give first:
SELECT part#,
COUNT(DISTINCT CASE WHEN make = '1' THEN application# END) make1_apps,
COUNT(DISTINCT application#) total_apps
FROM [mytable]
GROUP BY part#
HAVING COUNT(DISTINCT CASE WHEN make = '1' THEN application# END)
= COUNT(DISTINCT application#)
ORDER BY part#
Thanks again!
Try this:
SELECT
apps.part#
, COUNT(*)
, SUM(CASE WHEN make = '1' THEN 1 ELSE 0 END)
FROM [mytable]
GROUP BY apps.part#
This solution replaces counting with calculating a sum, and supplying 1 for matching items and 0 for non-matching ones.
To filter out the records where the two counts are different, add a HAVING clause:
SELECT
apps.part#
, COUNT(*)
, SUM(CASE WHEN make = '1' THEN 1 ELSE 0 END)
FROM [mytable]
GROUP BY apps.part#
HAVING SUM(CASE WHEN make = '1' THEN 1 ELSE 0 END) = COUNT(*)
SELECT [Part Number],
SUM(CASE WHEN [Make ID] = 1 THEN 1 ELSE 0 END),
COUNT(*)
FROM tableName
GROUP BY [Part Number]
SQLFiddle Demo
UPDATE 1
SELECT [Part Number],
SUM(CASE WHEN [Make ID] = 1 THEN 1 ELSE 0 END),
COUNT(*)
FROM tableName
GROUP BY [Part Number]
HAVING SUM(CASE WHEN [Make ID] = 1 THEN 1 ELSE 0 END) = COUNT(*)
SQLFiddle Demo
another way more similar to yours:
select d.[Part Number], count(d.[Part Number]), o.ones
from
data d
cross apply
(
select count(*)
from data d2
where d2.[Part Number] = d.[Part Number]
and d2.[Make ID] = 1
) o (ones)
group by d.[Part Number], o.ones
SQLFiddle
to fullfill your second request add:
having count(d.[Part Number]) = o.ones
SELECT part#,
COUNT(DISTINCT CASE WHEN make = '1' THEN application# END) make1_apps,
COUNT(DISTINCT application#) total_apps
FROM [mytable]
GROUP BY part#
HAVING COUNT(DISTINCT CASE WHEN make = '1' THEN application# END)
= COUNT(DISTINCT application#)
ORDER BY part#;
The HAVING clause ensures the two counts match.