Two tables with one value - sql-server

[enter image description here][1]can someone please advise on this?
These two tables have the renters name, one is in r.renter.own1 and the other is in t.renter.name
Acct Owner1 Owner2
256 ABC NULL
478 NULL FGH
What can I do to get it as?
Acct Owner
256 ABC
478 FGH
https://i.stack.imgur.com/Y8xVW.png

Select Acct, coalesce(Owner1, Owner2) as Owner
from myTable;

Related

How to aggregate several columns into a JSON file in HIVE and avoid nulls

user_id reservation_id nights price
--------------------------------------
AAA 10001 1 100
AAA 10002 1 120
BBB 20003 7 350
ccc 10005 150
DDD 10007 3
CCC 10006 5
to
user_id reservation_details
AAA [{"nights":"1", "price":"100"}, {"nights":"1","price":"120"}]
BBB [{"nights":"7", "price":"350"}]
CCC [{"price":"150"}, {"nights":"3"}]
DDD [{"nights":"5"}]
Here my query is
select user_id
,concat("
{",concat_ws(',',collect_list(concat(string(reservation_id),":
{'nights':",string(nights),",'price':",string(price),"}"))),"}") as
reservation_details
from mytable
group by user_id
I want to eliminate the columns which have value as nulls and convert that single quotes into double quotes which looks like a exact JSON.
Using in-built datatypes map and array along with a case expression to handle nulls.
select user_id,collect_list(map_nights_price)
from (select user_id,
case when nights is null then map('price',price)
when price is null then map('nights',nights)
else map('nights',nights,'price',price) end as map_nights_price
from mytable
where not (price is null and nights is null) --ignore row where price and nights are null
) t
group by user_id

SQL Server select join detect if common column between two tables are different

I am trying to write a function to check between two tables which have a common column with the same name and ID values.
Table 1: CompanyRecords
CompanyRecordsID CompanyId CompanyName CompanyProcessID
-----------------------------------------------------------
1 222 Sears 123
2 333 JCPenny 456
Table 2: JointCompanies
JointCompaniesID CompanyId CompanyName ComanyProcessID
-----------------------------------------------------------
3 222 KMart 123
4 444 Walmart 001
They both use the same foreign key CompanyProcessID with value 123.
How do I write a select statement when it is passed the CompanyProcessID to tell if the CompanyId has changed for the same CompanyProcessId.
I assume it is a join between the two tables with WHERE CompanyProcessID
Thanks for any help.
Is this what you want?
select max(case when cr.name = jc.name then 0 else 1 end) as name_not_same
from CompanyRecords cr join
JointCompanies jc
on cr.ComanyProcessID = jc.ComanyProcessID
where cr.ComanyProcessID = ?

How to filter groups?

I have a table like this:
Address AccountName AccountId
-------------------------------------------------------
10007 Cougar Country Smith 107
90026 Hunters Pond Scott 106
10008 Indigo Run Mary 108
70023 Kopplin Road John 102
70023 Kopplin Road John 103
70023 Kopplin Road Peter 104
70023 Kopplin Road Steve 105
70018 Oaks Drive Joe 100
70018 Oaks Drive Lisa 101
This is a result of joining two tables actually
with OrderBy Address. Table has records where
Address and/or AccountName columns
can have identical values among multiple rows,
while AccountId column would always be different.
How to get record groups where:
a) Address is same and AccountName is different
b) Address is same and AccountName is same
Also number of records in a group > 1.
I need all fields from table.
Here is the output I need to have:
a) Address is same and AccountName is different:
Address AccountName AccountId
-------------------------------------------------------
70023 Kopplin Road Peter 104
70023 Kopplin Road Steve 105
70018 Oaks Drive Joe 100
70018 Oaks Drive Lisa 101
b) Address is same and AccountName is same:
Address AccountName AccountId
-------------------------------------------------------
70023 Kopplin Road John 102
70023 Kopplin Road John 103
Thanks a lot
Perhaps something like this? It's certainly possible this could be improved if we knew more about your base query.
with data as (
<yourQuery>
)
select
case when count(*) over (partition by Address, AccountName) > 1
then 'Same Address and AccountName' else 'Same Address only'
end as Tag,
from data
where Address in (
select Address
from data
group by Address
having count(*) > 1
)
order by Tag, Address, AccountName
According to a comment on another answer it appears you may also want to handle repeated account names with different addresses. The question as posted describes something different. If you need this requirement to be incorporated into an answer you'll need to update the question accordingly.
Edit per your comment
with data as (
<yourQuery>
), dups as (
select *,
case when count(*) over (partition by Address, AccountName) > 1
then 'Same Address and AccountName' else 'Same Address only'
end as Tag,
from data
where Address in (
select Address
from data
group by Address
having count(*) > 1
)
)
select * from dups
where Tag = 'Same Address and AccountName' -- or 'Same Address only'
order by Tag, Address, AccountName
It still isn't totally clear what you want but this should get you close.
with SortedResults as
(
select Address
, AccountName
, AccountId
, ROW_NUMBER() over (partition by Address, AccountName order by AccountId) as RowNum
from SomeTable
)
select *
from SortedResults
where RowNum > 1
Declare #YourTable table (Address varchar(150),AccountName varchar(50),AccountID varchar(50))
Insert Into #YourTable values
('10007 Cougar Country','Smith','107'),
('90026 Hunters Pond' ,'Scott','106'),
('10008 Indigo Run' ,'Mary' ,'108'),
('70023 Kopplin Road' ,'John' ,'102'),
('70023 Kopplin Road' ,'John' ,'103'),
('70023 Kopplin Road' ,'Peter','104'),
('70023 Kopplin Road' ,'Steve','105'),
('70018 Oaks Drive' ,'Joe' ,'100'),
('70018 Oaks Drive' ,'Lisa' ,'101')
;with cteBase as (Select *,RowNr=Row_Number() over (Partition By Address,AccountName Order by AccountID) from #YourTable)
,cteLvl1 as (Select Address,GrpLvl1=IIF(count(*)>1,1,0) From cteBase Group by Address)
,cteLvl2 as (Select Address,AccountName,GrpLvl2=IIF(max(RowNr)>1,1,0) From cteBase Group by Address,AccountName)
Select Class=IIF(GrpLvl1+GrpLvl2=0,'None',IIF(GrpLvl1+GrpLvl2=1,'Group','Sub-Group'))
,A.Address
,A.AccountName
,A.AccountID
From cteBase A
Join cteLvl1 B on (A.Address=B.Address)
Join cteLvl2 C on (A.Address=B.Address and A.AccountName=C.AccountName)
Where GrpLvl1+GrpLvl2>=1
Order By GrpLvl1+GrpLvl2,2,3,4
Returns
Class Address AccountName AccountID
Group 70018 Oaks Drive Joe 100
Group 70018 Oaks Drive Lisa 101
Group 70023 Kopplin Road Peter 104
Group 70023 Kopplin Road Steve 105
Sub-Group 70023 Kopplin Road John 102
Sub-Group 70023 Kopplin Road John 103

How i can solve query like that

I have one problem in sql server.I have some records like
PKId EquipmentID StudentId Issueddate Returneddate
1 116 230 2014-01-14 17:14:58.940 2014-01-18 14:12:038.876
2 116 237 2014-01-14 17:14:58.940 NULL
3 117 400 2014-01-14 17:14:58.940 2014-01-18 14:12:038.876
Here EquipmentID and StudentId are the foreign key.We need to write a query which gives us data based on Returneddate.We need to check condition one like in first row equipmentid is 116 and it's assigned to studentId 230 where Returneddate is not null means for now this 116 equipment is free means it is unassiged but in the next line same equipment is assigned to student 237 and hiis returneddate is NULL means this equipment is assined to someone and in last case equipmentid 117 assigned to studentid 400 and it's returneddate is not null means it is available.
So we need to show only those records which is available.If i took this case as example then it will give me
3 117 400 2014-01-14 17:14:58.940 2014-01-18 14:12:038.876 row as a output.
I Tried:
select * from Equipment where (EquipmentID not in (select EquipmentID
from PEquip where Returneddate is null))
Please help me.
Hope you understand.
If I've got it right you need EquipmentID for which there are no rows with NULL Returneddate.
SELECT * FROM T as T1
WHERE NOT EXISTS (SELECT * FROM T
WHERE EquipmentID=T1.EquipmentID
AND Returneddate IS NULL)
select * from EuipmentDetails where EquipmentID
not in (select EquipmentID from EuipmentDetails where Returneddate is NULL )
Try this:
select * from theTable t1 where returneddate =
(select max Issueddate from theTable t2 where t1.EquipmentId = t2.EquipmentId)
and returneddate is not NULL;
Assuming that the order of PkId is consistent with the chronology of the data, I'd go with
SELECT PKId, EquipmentID, StudentId, Issueddate, Returneddate
FROM Equipment E
INNER JOIN (SELECT MAX(PKId) AS PKId FROM Equipment GROUP BY EquipmentId) AS T
ON E.PKId = T.PKId
WHERE E.ReturnedDate IS NOT NULL
Logic: select the latest entry for each EquipmentId, IF the latest entry has ReturnedDate not null.

SQL query like GROUP BY with OR condition

I'll try to describe the real situation. In our company we have a reservation system with a table, let's call it Customers, where e-mail and phone contacts are saved with each incoming order - that's the part of a system I can't change. I'm facing the problem how to get count of unique customers. With the unique customer I mean group of people who has either the same e-mail or same phone number.
Example 1: From the real life you can imagine Tom and Sandra who are married. Tom, who ordered 4 products, filled in our reservation system 3 different e-mail addresses and 2 different phone numbers when one of them shares with Sandra (as a homephone) so I can presume they are connected somehow. Sandra except this shared phone number filled also her private one and for both orders she used only one e-mail address. For me this means to count all of the following rows as one unique customer. So in fact this unique customer may grow up into the whole family.
ID E-mail Phone Comment
---- ------------------- -------------- ------------------------------
0 tom#email.com +44 111 111 First row
1 tommy#email.com +44 111 111 Same phone, different e-mail
2 thomas#email.com +44 111 111 Same phone, different e-mail
3 thomas#email.com +44 222 222 Same e-mail, different phone
4 sandra#email.com +44 222 222 Same phone, different e-mail
5 sandra#email.com +44 333 333 Same e-mail, different phone
As ypercube said I will probably need a recursion to count all of these unique customers.
Example 2: Here is the example of what I want to do.Is it possible to get count of unique customers without using recursion for instance by using cursor or something or is the recursion necessary ?
ID E-mail Phone Comment
---- ------------------- -------------- ------------------------------
0 linsey#email.com +44 111 111 ─┐
1 louise#email.com +44 111 111 ├─ 1. unique customer
2 louise#email.com +44 222 222 ─┘
---- ------------------- -------------- ------------------------------
3 steven#email.com +44 333 333 ─┐
4 steven#email.com +44 444 444 ├─ 2. unique customer
5 sandra#email.com +44 444 444 ─┘
---- ------------------- -------------- ------------------------------
6 george#email.com +44 555 555 ─── 3. unique customer
---- ------------------- -------------- ------------------------------
7 xavier#email.com +44 666 666 ─┐
8 xavier#email.com +44 777 777 ├─ 4. unique customer
9 xavier#email.com +44 888 888 ─┘
---- ------------------- -------------- ------------------------------
10 robert#email.com +44 999 999 ─┐
11 miriam#email.com +44 999 999 ├─ 5. unique customer
12 sherry#email.com +44 999 999 ─┘
---- ------------------- -------------- ------------------------------
----------------------------------------------------------------------
Result ∑ = 5 unique customers
----------------------------------------------------------------------
I've tried a query with GROUP BY but I don't know how to group the result by either first or second column. I'm looking for let's say something like
SELECT COUNT(*) FROM Customers
GROUP BY Email OR Phone
Thanks again for any suggestions
P.S.
I really appreciate the answers for this question before the complete rephrase. Now the answers here may not correspond to the update so please don't downvote here if you're going to do it (except the question of course :). I completely rewrote this post.Thanks and sorry for my wrong start.
Here is a full solution using a recursive CTE.
;WITH Nodes AS
(
SELECT DENSE_RANK() OVER (ORDER BY Part, PartRank) SetId
, [ID]
FROM
(
SELECT [ID], 1 Part, DENSE_RANK() OVER (ORDER BY [E-mail]) PartRank
FROM dbo.Customer
UNION ALL
SELECT [ID], 2, DENSE_RANK() OVER (ORDER BY Phone) PartRank
FROM dbo.Customer
) A
),
Links AS
(
SELECT DISTINCT A.Id, B.Id LinkedId
FROM Nodes A
JOIN Nodes B ON B.SetId = A.SetId AND B.Id < A.Id
),
Routes AS
(
SELECT DISTINCT Id, Id LinkedId
FROM dbo.Customer
UNION ALL
SELECT DISTINCT Id, LinkedId
FROM Links
UNION ALL
SELECT A.Id, B.LinkedId
FROM Links A
JOIN Routes B ON B.Id = A.LinkedId AND B.LinkedId < A.Id
),
TransitiveClosure AS
(
SELECT Id, Id LinkedId
FROM Links
UNION
SELECT LinkedId Id, LinkedId
FROM Links
UNION
SELECT Id, LinkedId
FROM Routes
),
UniqueCustomers AS
(
SELECT Id, MIN(LinkedId) UniqueCustomerId
FROM TransitiveClosure
GROUP BY Id
)
SELECT A.Id, A.[E-mail], A.Phone, B.UniqueCustomerId
FROM dbo.Customer A
JOIN UniqueCustomers B ON B.Id = A.Id
Finding groups that have only same Phone:
SELECT
ID
, Name
, Phone
, DENSE_RANK() OVER (ORDER BY Phone) AS GroupPhone
FROM
MyTable
ORDER BY
GroupPhone
, ID
Finding groups that have only same Name:
SELECT
ID
, Name
, Phone
, DENSE_RANK() OVER (ORDER BY Name) AS GroupName
FROM
MyTable
ORDER BY
GroupName
, ID
Now, for the (complex) query you describe, let's say we have a table like this instead:
ID Name Phone
---- ------------- -------------
0 Kate +44 333 333
1 Sandra +44 000 000
2 Thomas +44 222 222
3 Robert +44 000 000
4 Thomas +44 444 444
5 George +44 222 222
6 Kate +44 000 000
7 Robert +44 444 444
--------------------------------
Should all these be in one group? As they all share name or phone with someone else, forming a "chain" of relative persons:
0-6 same name
6-1-3 same phone
3-7 same name
7-4 same-phone
4-2 same name
2-5 bame phone
For the dataset in the example you could write something like this:
;WITH Temp AS (
SELECT Name, Phone,
DENSE_RANK() OVER (ORDER BY Name) AS NameGroup,
DENSE_RANK() OVER (ORDER BY Phone) AS PhoneGroup
FROM MyTable)
SELECT MAX(Phone), MAX(Name), COUNT(*)
FROM Temp
GROUP BY NameGroup, PhoneGroup
I don't know if this is the best solution, but here it is:
SELECT
MyTable.ID, MyTable.Name, MyTable.Phone,
CASE WHEN N.No = 1 AND P.No = 1 THEN 1
WHEN N.No = 1 AND P.No > 1 THEN 2
WHEN N.No > 1 OR P.No > 1 THEN 3
END as GroupRes
FROM
MyTable
JOIN (SELECT Name, count(Name) No FROM MyTable GROUP BY Name) N on MyTable.Name = N.Name
JOIN (SELECT Phone, count(Phone) No FROM MyTable GROUP BY Phone) P on MyTable.Phone = P.Phone
The problem is that here are some joins made on varchars and could end up in increasing execution time.
Here is my solution:
SELECT p.LastName, P.FirstName, P.HomePhone,
CASE
WHEN ph.PhoneCount=1 THEN
CASE
WHEN n.NameCount=1 THEN 'unique name and phone'
ELSE 'common name'
END
ELSE
CASE
WHEN n.NameCount=1 THEN 'common phone'
ELSE 'common phone and name'
END
END
FROM Contacts p
INNER JOIN
(SELECT HomePhone, count(LastName) as PhoneCount
FROM Contacts
GROUP BY HomePhone) ph ON ph.HomePhone = p.HomePhone
INNER JOIN
(SELECT FirstName, count(LastName) as NameCount
FROM Contacts
GROUP BY FirstName) n ON n.FirstName = p.FirstName
LastN FirstN Phone Comment
Hoover Brenda 8138282334 unique name and phone
Washington Brian 9044563211 common name
Roosevelt Brian 7737653279 common name
Reagan Charles 7734567869 unique name and phone

Resources