UNION with dissimilar columns - sql-server

TABLE A
ID Name Age
1 John 22
TABLE B
ID Name
5 Erik
I want result like
ID Name Age
1 John 22
5 Erik
When I am performing UNION giving error
"All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists."
How to get desired result?

You could supply a dummy column in lieu of the missing one that returns NULL as below.
SELECT ID,
Name,
Age
FROM TABLE_A
UNION ALL
SELECT ID,
Name,
NULL
FROM TABLE_B

Related

TSQL to choose a record that meets the criteria or first one

I have a table for company phone numbers and one of the columns is IsPrimary which is a boolean type. The table looks like this:
CompanyId | AreaCode | PhoneNumber | IsPrimary
123 212 555-1212 0
234 307 555-1234 1
234 307 555-4321 0
As you can see in the first record, even though the phone number is the only one for CompanyId: 123, it's not marked as the primary.
In such cases, I want my SELECT statement to return the first available number for that company.
My current SELECT statement looks like this which does NOT return a number unless it's set as the primary number.
SELECT *
FROM CompanyPhoneNumbers AS t
WHERE t.IsPrimary = 1
How can I modify this SELECT statement so that it includes the phone number for CompanyId: 123?
The query might be different depending on what you are actually up to.
If you already have the CompanyId and only need the phone number for it, that's easy:
select top (1) pn.*
from dbo.CompanyPhoneNumbers pn
where pn.CompanyId = #CompanyId -- A parameter provided externally, by calling code for instance
order by pn.IsPrimary desc;
However, if you need all companies' data, including one of their phones (for example, you might be going to create a view for this), then you need a correlated subquery:
select c.*, oa.*
from dbo.Companies c
outer apply (
select top (1) pn.*
from dbo.CompanyPhoneNumbers pn
where pn.CompanyId = c.Id
order by pn.IsPrimary desc
) oa;
I have deliberately used outer instead of cross apply, otherwise it will filter out companies with no phone numbers listed.
You can achieve this using an apply statement. This looks at the exact same table and returns the record with the highest IsPrimary so, this would return the records with a 1 in that column. If there are more than one marked as primary or not as primary, then it returns the phone number, with area code, in ascending order.
select b.*
from CompanyPhoneNumbers a
cross apply (
select top 1
*
from CompanyPhoneNumbers b
where b.CompanyId = a.CompanyId
order by b.IsPrimary desc
,b.AreaCode
,b.PhoneNumber
) b

Splitting a row based on a condition

i have a scenario. In a table i got 2 fields which checks for a patients. For example, if a patient has 'A' or if a patient has 'B'.
But when i pull the record, i want 2 records, one for A and one for B. I know this could be done using UNION ALL but is there a different way to do that because UNION ALL will be way too bulky code for me. Please help!
Example would be like this.
In Table Patients
PatientID Name Age HasA HasB
1234 Sad 18 Yes Yes
4567 Happy 40 Yes No
8901 confused 25 No Yes
so my query should return:
PatientID Name Age Has
1234 Sad 18 A
1234 Sad 18 B
4567 Happy 40 A
8901 confused 25 B
so a sort of duplicate row if it has both A and B.
Although I would assume union all would perform better, but at least this is one way to do it:
select PatientID, Name, Age, t2.Code as Has
from Table1 t1
left outer join Table2 t2 on
((t2.Code = 'A' and t2.Yes = T1.HasA) or
(t2.Code = 'B' and t2.Yes = T1.HasB))
Example in SQL Fiddle
Table2 is just a simple table that has A, Yes and B, Yes rows.
Try.
Fiddle Demo
select PatientId,Name,
(case
when HasA='Yes' Then 'A'
End) as Has
from Table1 where HasA='Yes'
Union All
select PatientId,Name,
(case
when HasB='Yes' Then 'B'
End) as Has
from Table1 where HasB='Yes'

Pivoting a single field in a table

I have a table of the following structure:
Name
Type
Line
UniqueID
Key
Value
I need to select all the fields except UniqueID field and add a key 'UniqueID' and a Value field with the value of the UniqueID to the result set.
For example if I have three records:
Name Type Line UniqueID Key Value
___________________________________________________________________
John Doe Employee 2 test333 SSN 123-45-2345
John Doe Employee 3 test333 Address 555 Rodeo Drive
Jane Doe Visitor 2 test444 SSN 345-67-8907
my result set would need to be:
Name Type Line Key Value
___________________________________________________
John Doe Employee 2 UniqueID test333
John Doe Employee 2 SSN 123-45-2345
John Doe Emplyee 3 Address 555 Rodeo Drive
Jane Doe Visitor 2 UniqueID test444
Jane Doe Visitor 2 SSN 345-67-8907
Do I use pivots? Can anyone point me into the right direction?
This is kind of an odd request, at least to me. But anyhow, you can approach it a few ways. One way is to use cross apply:
select
name,
type,
line,
newkey,
newvalue
from
table1
cross apply
( values
('UniqueID',uniqueid),
('SSN',Value),
('Address',Value)
) c
(newkey,newvalue)
SQL Fiddle demo
Based on your comments, we'll chuck the union all method.
Here is an incredibly ugly and kludgy unpivot, combined with a union (to get the unique ids):
select
name,
type,
line,
newkey2,
newvalue
from
(select
name,
type,
line,
[key],
[value]
from table1) t1
unpivot
(
newvalue for newkey in ([Value])
) u
unpivot
(newkey2 for newvalue2 in ([key])) u2
union all
select
name,
type,
line,
'UniqueID',
Uniqueid
from
table1
Unpivot SQL Fiddle

how to select a row based on a single distinct value

If i have 4 rows and want to select rows based on a single column's distinct values and dont mind which info it uses for the rest of the row, how do i do this? There doesn't seem to be a 'distinct' function for single cols whilst maintaining rest of row data.
eg
Name, value
john 1
john 2
michael 3
michael 5
result
john 1
michael 5
note it could have been john 2 or michael 3, i dont care which row for John or Michael it uses for the rest of the values.
GROUP BY Name and use any aggregate function with the value MIN or MAX since you don't care about the value of it:
SELECT Name, MIN(value)
FROM table
GROUP BY Name
Try this
select a.* from TAbleName a
inner join
(
select distinct name,min(Id) as id from TAbleName
group by name
) as b
on a.name= b.name
and a.id=b.id

Include NULL in each "Details Group" in SSRS

In SSRS I have a List with, say, a table with two columns: name and number e.g.:
NAME NUMBER
John 123
John 456
John NULL
Name is never null, but number may be. In this case I want the report to include the NULL in each group, like this:
GROUP 1:
John NULL
John 123
GROUP 2:
John NULL
John 456
The SSRS, however, puts the null in a group on its own. How do I accomplish this?
You have told SSRS to group on the NUMBER column, so it will generate a separate group for each value in the NUMBER column and then display those rows. To get what you want, you have to make the data set have the rows you want.
Select Name, Number, cast(Number as varchar(50)) as displayvalue
From mytable
UNION ALL
Select m.Name, m.Number, 'NULL' as displayvalue
From mytable m
Where exists(Select 1 from mytable where Name=m.Name and Number is NULL)
Group by Name, Number
Then group on the Number column but report on the DisplayValue column.

Resources