Give alias to query result - sql

Let's take this piece of code as example:
SELECT *
FROM (SELECT Players.Team, AVG(Players.BirthDate) AS AvgBirthDate
FROM Players
GROUP BY Players.Team)
WHERE AvgBirthDate = (SELECT MAX(AvgBirthDate)
FROM (SELECT Players.Team, AVG(Players.BirthDate) AS AvgBirthDate
FROM Players
GROUP BY Players.Team))
My question is if there is a way to give an alias to the whole query result so that something like this would be possible:
SELECT *
FROM (SELECT Players.Team, AVG(Players.BirthDate) AS AvgBirthDate
FROM Players
GROUP BY Players.Team) AS QueryResult
WHERE AvgBirthDate = (SELECT MAX(AvgBirthDate)
FROM QueryResult)
URL to the code/db

You can use With clause. If it's not possible, you should consider using a view or a temporary table to store the result of a query that might be use several times after its execution.

Related

Want to concatenate column of the second query to the first query but getting errors such as "query block has incorrect number of result columns"

SELECT
ID, PRIM_EMAIL, SEC_EMAIL, PHONE
FROM
STUDENTS.RECORDS
WHERE
ID IN (SELECT ID FROM STUDENTS.INFO WHERE ROLL_NO = '554')
UNION
SELECT NAME
FROM STUDENTS.INFO
WHERE ROLL_NO = '554';
Here Roll_No is a user inserted data so for now I have hard coded it. Basically with the help of ROLL_NO I sort the STUDENTS_INFO table from where I get the ID and based on that I try to get PRIM_EMAIL, SEC_EMAIL, PHONE from the STUDENTS.RECORDS table while matching the foreign keys of both the tables. In addition to the current result set I also want to have the prov_name column.
Any help is very much appreciated. Thank you!
I suspect that you want to put all this information on the same row, which suggests a join rather than union all:
select
r.ID,
r.PRIM_EMAIL,
r.SEC_EMAIL,
r.PHONE,
r.NAME
from STUDENTS.RECORDS r
inner join STUDENTS.INFO i ON i.ID = r.ID
where I.ROLL_NO = '554';
I think the source of your error query block has incorrect number of result columns is coming from trying to union together a table with 4 columns (id, prim_email, sec_email, phone) with 1 column (name).
From your question, I am gathering that you want a single table of id, prim_email, sec_email, phone from students.records and name from students.info.
I think the following query using CTE's might get you (partially) to your final result. You may want to refactor for optimizing performance.
with s_records as ( select * from students.records ),
s_info as ( select * from students.info ),
joined as (
select
s_records.id,
s_records.prim_email,
s_records.sec_email,
s_records.phone,
s_info.name
from s_records
left join s_info
on s_records.roll_no = s_info.roll_no
where roll_np = '554' )
select * from joined
Overall, I think that a join will be part of your solution rather than a union :-)

PyPika how to select star minus a column

I'm trying to use PyPika to build a select statement. Both tables have an id column, and I'm trying to select all columns from both tables except the id column from the first table.
This is the query I want to end up with, which runs properly in BigQuery:
SELECT t.* EXCEPT(id), s.* from t join s on t.id = s.id
I haven't been able to figure out how to get the EXCEPT into the select clause.
I've tried the following syntax, but the except_of() isn't allowed in this context:
t = Table("t")
s = Table("s")
query = Query.from_(t).join(s).on(t.id == s.id).select(t.star.except_of("id")).select(s.star)
I also tried a custom function, but that puts an invalid comma in the resulting query. This is what I tried:
except_select = CustomFunction("EXCEPT", ["column_to_exclude"])
query = Query.from_(t).join(s).on(t.id == s.id).select(t.star).except_select("id")).select(s.star)
which incorrectly generates
SELECT t.*, EXCEPT(id), s.* from t join s on t.id = s.id
Does anyone have any suggestions on how to solve this problem?

selecting minimum value depending on other value

Is there any better way for below sql query? Don't want to drop and create temporary table just would like to do it in 1 query.
I am trying to select minimum value for price depending if its order sell where obviously price is higher then in buy and it just shows 0 results when I try it.
DROP TABLE `#temporary_table`;
CREATE TABLE `#temporary_table` (ID int(11),region int(11),nazwa varchar(100),price float,isBuyOrder int,volumeRemain int,locationID int,locationName varchar(100),systemID int,security_status decimal(1,1));
INSERT INTO `#temporary_table` SELECT * FROM hauling WHERE isBuyOrder=0 ORDER BY ID;
SELECT * FROM `#temporary_table`;
SELECT * FROM `#temporary_table` WHERE (ID,price) IN (select ID, MIN(price) from `#temporary_table` group by ID) order by `ID`
UPDATE: when I try nvogel answer and checked profiling thats what I get:
Any chance to optimize this or different working way with 700k rows database?
Try this:
SELECT *
FROM hauling AS h
WHERE isBuyOrder = 0
AND price =
(SELECT MIN(t.price)
FROM hauling AS t
WHERE t.isBuyOrder = 0
AND t.ID = h.ID);
You don't need a temporary table at all. You can basically use your current logic:
SELECT h.*
FROM hauling h
WHERE h.isBuyOrder = 0 AND
(h.id, h.price) IN (SELECT h2.id, MIN(h2.price)
FROM hauling h2
WHERE h2.isBuyOrder = 0
)
ORDER BY h.id
There are many other ways to write similar logic. However, there is no need to rewrite the logic; you just need to include the comparison on isBuyOrder in the subquery.
Note that not all databases support IN with tuples. If your database does not provide such support, then you would need to rewrite the logic.

SQL DB2 store query result into variable

Usind a DB2 tables:
This is what is done manually in a table
select app_id from table_app where APP_NAME='App_Temp';
gets me an ID, say it's 234
I copy than and do:
select * form table_roles where role_app_id=234;
gets me a row , which is my desired end result.
Is there a way save the result of the first one into a variable and do the second query without the manual step in between using local variables?
I know, you can query out the information with a very simple join between two tables, but I'd like to know, how it works with variables. Is there a way?
Just can just plug it in:
select *
from table_roles
where role_app_id = (select app_id from table_app where APP_NAME = 'App_Temp');
If there can be more than one match, use in instead of =.
You can also phrase this as a join:
select r.*
from table_roles r join
table_app
on r.role_app_id = a.app_id and APP_NAME = 'App_Temp';
However, this might return duplicates, if two apps have the same name. In that case, use select distinct:
select distinct r.*
from table_roles r join
table_app
on r.role_app_id = a.app_id and APP_NAME = 'App_Temp';

I need to use a temporary attribute I created in my Select Statement in order to use it in a Where statement?

I used a view to get the right answer but I want it in one SQL statement, also I was wondering if there was a way to do it without projecting out the tables again.
So can I COUNT(OW_OWNERNO) AS NO_HOUSES and use the NO_HOUSES in my where clause? Is there a way to define it as such.
This statement is trying to calculate how many houses the people in the data base own and project only those who have more than one home.
CREATE VIEW NUMHOUSE AS
SELECT OW_FIRSTNAME, OW_LASTNAME, **COUNT(OW_OWNERNO) AS NO_HOUSES**
FROM (rentproperty JOIN OWNER ON RP_OW_OWNERNO = OW_OWNERNO)
WHERE RP_TYPE = 'House'
GROUP BY OW_OWNERNO;
SELECT * FROM NUMHOUSE
WHERE NO_HOUSES > 1;
Here are two ways. The first one uses a having clause suggested by Fabio.
SELECT OW_FIRSTNAME, OW_LASTNAME, COUNT(OW_OWNERNO) AS NO_HOUSES
FROM (rentproperty JOIN OWNER ON RP_OW_OWNERNO = OW_OWNERNO)
WHERE RP_TYPE = 'House'
GROUP BY OW_OWNERNO
having no_houses > 1 -- note some dbs might not let you use an alias here
This one uses a subquery
select * from (
SELECT OW_FIRSTNAME, OW_LASTNAME, COUNT(OW_OWNERNO) AS NO_HOUSES
FROM (rentproperty JOIN OWNER ON RP_OW_OWNERNO = OW_OWNERNO)
WHERE RP_TYPE = 'House'
GROUP BY OW_OWNERNO
) temp
where no_houses > 1
They work equally well.
I think you should use HAVING instead of WHERE
Example
SELECT * FROM NUMHOUSE HAVING COUNT(NO_HOUSES) > 1;