UNION types double precision and character varying cannot be matched - postgresql

I am trying to run a program from my following database
DATABASE
But i am getting the error "UNION types double precision and character varying cannot be matched" every time I try to run the program
My code is
SELECT
EXTRACT(YEAR
FROM AGE(users.dob)) AS Age,
users.gender,
app.name AS App
FROM users
LEFT OUTER JOIN app_user_profile
ON users.id = app_user_profile.users_id
LEFT OUTER JOIN app
ON app_user_profile.app_id = app.id
UNION
SELECT cities.name AS City, provinces.name AS Province, countries.name AS Country
FROM cities
LEFT OUTER JOIN provinces
ON cities.country_id = provinces.country_id
LEFT OUTER JOIN countries
ON provinces.country_id = countries.country_id

UNIONs in PostgreSQL must have the same number of columns and the columns must be of "compatible data types".
Judging from the names of your columns, these seem to be totally different things that you want to UNION. Which is unusual, but it can be done. The biggest problem seems to be between Age and City which are a number and text/varchar, respectively. If you cast Age as text, the UNION should work.
SELECT
EXTRACT(YEAR
FROM AGE(users.dob))::text AS Age,
....
Type casting can either be done with Column::<new type> or Cast(Column, <new type>). The first version is a custom PostgreSQL syntax and easy to type, and the second version conforms to SQL standards.

Related

PostgreSQL - in WITH RECURSIVE function, adding a column to select causes a different column reference to become ambiguous

I'm working on the last 'Recursion' exercise from pgexercises.com. There's a table of members, and some members were recommended by other members. The first exercise got me to find the upward recommender chain from a specified member ID - member 27 was recommended by member 20, who was recommended by member 5, who was recommended by member 1, so I created a recursive CTE that finds the names of all of those members:
WITH RECURSIVE recommenders(recommender) AS (
SELECT recommendedby FROM cd.members WHERE memid = 27
UNION ALL
SELECT recommendedby
FROM cd.members mems INNER JOIN recommenders recs
ON mems.memid = recs.recommender
)
SELECT recs.recommender, mems.firstname, mems.surname
FROM recommenders recs INNER JOIN cd.members mems
ON recs.recommender = mems.memid
This works just fine, and produces the following table:
recommender
firstname
surname
20
Matthew
Genting
5
Gerald
Butters
1
Darren
Smith
The last exercise wants me to, in essence, produce a CTE that contains the upward recommender chains for all members. So it will have an extra column (memid), and there'll be three rows with memid=27 (which will be otherwise the same as those three rows shown), and there'll be two rows with memid=20 (which will otherwise be the same as the bottom two rows), and there'll be one row with memid=5 (which will otherwise be the same as the bottom row), and a bunch of other rows for all the upward chains of all the other members.
Anyway that's all the premise. So, to work towards this, I started tweaking my solution. Firstly, I ditched the selection at the end (to simplify what I was working on), and removed the WHERE memid=27 clause on the second line:
WITH RECURSIVE recommenders (recommender) AS (
SELECT recommendedby FROM cd.members
UNION ALL
SELECT recommendedby
FROM cd.members mems INNER JOIN recommenders recs
ON mems.memid = recs.recommender
)
SELECT * FROM recommenders;
This worked fine, and generated lots of rows, some of them containing NULL (not every member has a recommendedby value). But then I tried changing the SELECT in the second row to
SELECT memid, recommendedby FROM cd.members
and suddenly I get an error:
SQL Error [42702]: ERROR: column reference "recommendedby" is ambiguous
The recommendedby column reference wasn't a problem before, but now that I want to also select memid, it suddenly becomes ambiguous. How can adding a new column to the selection can make a different column reference ambiguous?

Sort in non-alpabetical order in postgresql

I'm automating a process at work where the output needs to be in a certain non-alphabetical order depending on a name (internal_product, type text) in addition to a number (type text). First I'm running a subquery where I collect information from four slightly different tables using joins. I then append the result with a union before the outer group by sums units and amounts. The pseudo-query is as follows:
select name, number, internal_product, sum(units), sum(amount) from (
select fields, sum(x)
from t1
join join-conditions
join join-conditions
group by name, number, internal_product
union
.....
select fields, sum(x)
from t5
join join-conditions
join join-conditions
group by name, number, internal_product
) as foo
group by name, number, internal_product
order by number, name;
I tried to change a column in a helper table used in one of the joins to an enum type since it is used in the outer group by (SO-thread) but the column type of course needs to be the same in the join-condition so the modified query was not valid. There are 30 product names so I would like to avoid using a CASE name as suggested by gbn and Guffa.
Are there other ways to apply a certain order in a order by?
It might be overkill or complicated for your case, but you could create a custom collation in postgres to sort the way you want. Have a look at the documentation.
https://www.postgresql.org/docs/11/collation.html

Using EXCEPT and flagging column differences

What Im looking to do is select data from a postgres table, which does not appear in another. Both tables have identical columns, bar the use of boolean over Varchar(1) but the issue is that the data in those columns do not match up.
I know I can do this with a SELECT EXCEPT SELECT statement, which I have implemented and is working.
What I would like to do is find a method to flag the columns that do not match up. As an idea, I have thought to append a character to the end of the data in the fields that do not match.
For example if the updateflag is different in one table to the other, I would be returned '* f' instead of 'f'
SELECT id, number, "updateflag" from dbc.person
EXCEPT
SELECT id, number, "updateflag":bool from dbg.person;
Should I be joining the two tables together, post executing this statement to identify the differences, from whats returned?
I have tried to research methods to implement this but have no found anything on the topic
I prefer a full outer join for this
select *
from dbc.person p1
full join dbg.person p2 on p1.id = p2.id
where p1 is distinct from p2;
The id column is assumed the primary key column that "links" the two tables together.
This will only return rows where at least one column is different.
If you want to see the differences, you could use a hstore feature
select hstore(p1) - hstore(p2) as columns_diff_p1,
hstore(p2) - hstore(p1) as columns_diff_p2
from dbc.person p1
full join dbg.person p2 on p1.id = p2.id
where p1 is distinct from p2;

Hive join tables on string field match

Hi I am trying to Left outer join on table onto another, the matching colums are type String.
Will Hive join on matching string columns or do they need to be converted to a different datatype?
My join ON Clause looks like
Select table1.para1, table2.para2
From table a
left outer Join Table b
On (table1.a=table2.b). A and B are strings, will this work?
Join on string will work. Just keep in mind that string matching will be case-sensitive.
Consider using functions like UPPER or LOWER.
For example,
select * from temp join new_temp on LOWER(temp.dept) = LOWER(new_temp.dept);

SELECT department_id, department_name, location_id, city FROM departments d Natural JOIN locations i using(location_id);

why is the query returning: ORA-00933: SQL command not properly ended and on removing the Natural keyword, it turns true(it executes)?????????
You either let Oracle do the join for you (using natural) or you do it explicitly.
Taken from Oracles documentation:
The following two statements are equivalent:
SELECT * FROM COUNTRIES NATURAL JOIN CITIES
SELECT * FROM COUNTRIES JOIN CITIES
USING (COUNTRY, COUNTRY_ISO_CODE)
You need to choose one approach or the other - at the moment you're trying to mix the two.