Getting a union query to create single records - sql

So I've put together a union query in access, but it displays in this fashion.
Name Column1 Column2
John 1 0
Jim 2 0
Mike 3 0
John 0 2
Jim 0 1
Mike 0 3
I would like for it to display like this:
Name Column1 Column2
John 1 2
Jim 2 1
Mike 3 3
In my select statement I'm setting column2 to 0 in the first portion of the union statement, and setting column1 to 0 in the second part. Now I realize that's why I'm getting the 0s in the end result, but is there a way to achieve my desired display with a union or do I need something more complex.
EDIT: The reason I set those columns to 0, was to avoid it asking me to enter a value when it could not find a value for column1 or 2.
PS. this is not my actual query, but rather just a quick example I was able to throw on here for question purposes.

select [Name], max([Column1]) as col1, max([Column2]) as col2
from ( put union query here ) as x
group by [Name]
edit -- didn't notice that your data was a query result and not a table. Put your current query where indicated in the from clause (as an inline view)

Related

Can you use an 'In' operator in a column expression?

Using Oracle 11. Trying to write some simple code for a conceptual demo. To illustrate what I'm trying to achieve, imagine I have SOMETABLE that has two columns: ID and NAME, like so:
ID NAME
---------
1 Tom
2 Larry
3 David
4 Steve
I'm trying to compute a third column that is true if the second column matches one of two hard-coded values. Something like this (which of course doesn't work.)
Select ID,
NAME,
(NAME in ('Larry', 'David')) as IS_FAVORITE
from SOMETABLE
and hoping to get this output...
ID NAME IS_FAVORITE
----------------------
1 Tom FALSE
2 Larry True
3 David True
4 Steve FALSE
Much to my surprise, I'm being told Oracle doesn't have the concept of booleans and I should be using 'numeric strings' or something like that, so this too is fine...
ID NAME IS_FAVORITE
----------------------
1 Tom 'N'
2 Larry 'Y'
3 David 'Y'
4 Steve 'N'
So can you use the IN operator in a column expression like this? If not, how would one compute the column that I am after?
You can achieve your expected output using case expression.
Select ID,
NAME,
CASE
WHEN
NAME in ('Larry', 'David')
THEN
'TRUE'
ELSE
'FALSE'
END as IS_FAVORITE
from SOMETABLE

SQL Rows to Columns if column values are unknown

I have a table that has demographic information about a set of users which looks like this:
User_id Category IsMember
1 College 1
1 Married 0
1 Employed 1
1 Has_Kids 1
2 College 0
2 Married 1
2 Employed 1
3 College 0
3 Employed 0
The result set I want is a table that looks like this:
User_Id|College|Married|Employed|Has_Kids
1 1 0 1 1
2 0 1 1 0
3 0 0 0 0
In other words, the table indicates the presence or absence of a category for each user. Sometimes the user will have a category where the value if false, sometimes the user will have no row for a category, in which case IsMember is assumed to be false.
Also, from time to time additional categories will be added to the data set, and I'm wondering if its possible to do this query without knowing up front all the possible category names, in other words, I won't be able to specify all the column names I want to count in the result. (Note only user 1 has category "has_kids" and user 3 is missing a row for category "married"
(using Postgres)
Thanks.
You can use jsonb funcions.
with titles as (
select jsonb_object_agg(Category, Category) as titles,
jsonb_object_agg(Category, -1) as defaults
from demog
),
the_rows as (
select null::bigint as id, titles as data
from titles
union
select User_id, defaults || jsonb_object_agg(Category, IsMember)
from demog, titles
group by User_id, defaults
)
select id, string_agg(value, '|' order by key)
from (
select id, key, value
from the_rows, jsonb_each_text(data)
) x
group by id
order by id nulls first
You can see a running example in http://rextester.com/QEGT70842
You can replace -1 with 0 for the default value and '|' with ',' for the separator.
You can install tablefunc module and use the crosstab function.
https://www.postgresql.org/docs/9.1/static/tablefunc.html
I found a Postgres function script called colpivot here which does the trick. Ran the script to create the function, then created the table in one statement:
select colpivot ('_pivoted', 'select * from user_categories', array['user_id'],
array ['category'], '#.is_member', null);

SQL using fallback column for match

Say I have a table in an sql database like
name age shoesize
---------------------
tom 20 NULL
dick NULL 4
harry 30 5
and I want an SQL statement that selects names that have age == X, or as a fallback, if no such names exist, use those with shoe size == Y. In other words, in this table, for X=20,Y=4 I should only get 'tom', while for X=25,Y=4 I should get only 'dick'. I can't do that with
SELECT name FROM table WHERE age = 20 OR shoe size = 4;
because that will select both tom and dick. I'm currently using
SELECT COALESCE ((SELECT name FROM tab WHERE age = 20),(SELECT name FROM tab WHERE shoesize = 4));
but is there a neater way? Also using coalesce like this doesn't allow me to get the whole row - i.e. I can't use SELECT * FROM tab, I can only select a single name.
You can use ORDER BY and FETCH FIRST 1 ROW ONLY or some similar clause:
SELECT name
FROM tab
ORDER BY (CASE WHEN age = X THEN 1
WHEN shoesize = Y THEN 2
ELSE 3
END)
FETCH FIRST 1 ROW ONLY;
Some databases spell FETCH FIRST 1 ROW ONLY like LIMIT or TOP or even something else.

SQL Server Stored Procedure SELECT DISTINCT

I'm working on deciphering some stored procedures and have minimal vocabulary on the subject. Can someone please explain to me what role this '1' serves in the below statement? I can not find any DISTINCT syntax tutorials to explain this. I'm referring to the actual "1" one in the statement.
USE TEST
GO
SET ANSI_NULLS, QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].sp_F_SQL
(#Id int)
WITH ENCRYPTION AS
SELECT DISTINCT
dbo.MAP_SQL.rID,
dbo.MAP_SQL.lID,
dbo.MAP_SQL.cID,
**1** as RESPFACT,
dbo.MAP_SQL.Longitude,
dbo.MAP_SQL.Latitude,
dbo.MAP_SQL.Altitude,
...
The 1 has nothing to do with DISTINCT. It just adds an output column titled RESPFACT that has a value of 1 for all rows. I suspect whatever is consuming the output need that column.
SELECT DISTINCT only returns the "distinct" rows from the output - meaning rows where ALL column values are equal.
e.g. if your output without distinct was
1 2 ABC DEF
2 3 GHI JLK
2 1 ABC DEF
1 2 ABC DEF
Then rows 1 and 4 would be seen as "equal" and ony one would be returned:
1 2 ABC DEF
2 3 GHI JLK
2 1 ABC DEF
Note that rows 1 and 3 are NOT equal even though 3 of the 4 column values match.
The 1 generates a column called RESPFACT. This always has the value of 1.
I cannot say why this is important for the sp_F_SQL procedure.
The distinct returns unique rows. If there are duplicate values for the columns in the select then only one row is returned. Clearly, the RESPFACT column is the same in all rows, so it does not affect the rows being returned.

Reorder integer except for value 0 with sql

I'm trying to get an ordered list of rows out of my MYSQL database table based upon an integer value 'place'.
SELECT * FROM mytable
ORDER BY place;
This works okay, except that all rows with value place=0 should appear at the end of the table.
So if my table is:
name place
---- -----
John 1
Do 2
Eric 0
Pete 2
it should become:
name place
---- -----
John 1
Do 2
Pete 2
Eric 0
order by case when place = 0 then 1 else 0 end asc, place asc
that way you get all the non-zeroes ordered first.
SELECT *
FROM myTable
ORDER BY place>0 DESC, place
is a solution without CASE
SELECT *
FROM myTable
ORDER BY CASE place WHEN 0 THEN 9999 ELSE place END
This approach implies that we known that 9999 (or some other value) is bigger than all possible values in the place column.
Alternatively we can sort by two values as in:
ORDER BY CASE place WHEN 0 THEN 0 ELSE -1 END, place