msql query FROM another msl query - mysql

I am new to SQL, so I am not too sure how to go about this query that I have to do ...
I have multiple tables which all have 2 columns that i want to take (date_added and path).
So I did an Union select ("date_added" and "path") for each table. So I now have a table with all rows from all the tables I want:
SELECT `date_added`, `path` FROM `art_1` UNION SELECT `date_added`, `path` FROM `art_5484`
This works fine, but now I need to get the row with the lowest date ( I use min function). So I want to do select on the table that I got from my last query so I do:
SELECT `path`
FROM cross_join = (SELECT `date_added`, `path` FROM `art_1` UNION SELECT `date_added`, `path` FROM `art_5484`)
WHERE `date_added` = MIN(`date_added`)
But this doesn't work; I am guessing it's a syntax error, but i can't see where ...
if anybody could help me out, that would be great !

One way to get the minimum date is to use order by and limit:
SELECT `path`
FROM (SELECT `date_added`, `path` FROM `art_1` UNION ALL
SELECT `date_added`, `path` FROM `art_5484`
) a
ORDER BY date_added DESC
LIMIT 1;
Note: this returns only one value, even if when there are duplicates. Also, I changed the UNION to UNION ALL. You should use UNION ALL by default, because UNION incurs the overhead of removing duplicates.

Related

SQL Query about percentage selection

I am trying to write a query for a condition:
If >=80 percent (4 or more rows as 4/5*100=80%) of the top 5 recent rows(by Date Column), for a KEY have Value =A or =B, then change the flag from fail to pass for the entire KEY.
Here is the input and output sample:
I have highlighted recent rows with green colour in the sample.
Can someone help me in this?
I tried till finding the top 5 recent rows by the foll code:
select * from(
select *, row_number() over (partition by "KEY") as 'RN' FROM (
select * from tb1
order by date desc))
where "RN"<=5
Couldnt figure what to be done after this
Test this:
WITH
-- enumerate rows per key group
cte1 AS ( SELECT *,
ROW_NUMBER() OVER (PARTITION BY `key` ORDER BY `date` DESC) rn
FROM sourcetable ),
-- take 5 recent rows only, check there are at least 4 rows with A/B
cte2 AS ( SELECT `key`
FROM cte1
WHERE rn <= 5
GROUP BY `key`
HAVING ( SUM(`value` = 'A') >= 4
OR SUM(`value` = 'B') >= 4 )
-- AND SUM(rn = 5) )
-- update rows with found key values
UPDATE sourcetable
JOIN cte2 USING (`key`)
SET flag = 'PASS';
5.7 version – Ayn76
Convert CTEs to subqueries. Emulate ROW_NUMBER() using user-defined variable.

ORDER BY clause is not working with UNION ALL

My question is as follows:
SELECT title, 'dossier' as Source FROM dossier
UNION ALL
SELECT title, 'contract' as Source FROM contract ORDER BY `time` LIMIT 5
time column is present in both tables, but MySQL throws the following error:
unknown column 'time' in 'order clause'
When I remove , 'dossier' as Source and , 'contract' as Source the query works correctly.
order by clause is applied on the union all overall selection here, which doesn't have the time column (only title and Source). What you can do is use a temporary table:
select `title`, `source` from (
select `title`, 'dossier' as `Source`, `time` from dossier
union all
select `title`, 'contract', `time` from contract
) tbl
order by `time`
limit 5
#Potashin has one method for solving this.
You should understand that the order by is not part of either select clause. It only knows about the columns that are being selected.
Another solution is easy enough . . . that is to simply include time in the result set. What is happening might be clearer if you use parentheses:
(SELECT title, 'dossier', time as Source
FROM dossier
)
UNION ALL
(SELECT title, 'contract', time as Source
FROM contract
)
ORDER BY `time`
LIMIT 5;
I should note that if the tables are large and they have indexes on time, then the following may be more efficient:
(SELECT title, 'dossier', time as Source
FROM dossier
ORDER BY `time`
LIMIT 5
)
UNION ALL
(SELECT title, 'contract', time as Source
FROM contract
ORDER BY `time`
LIMIT 5
)
ORDER BY `time`
LIMIT 5;

Distinguish Output while using UNION in MySQL

I am using UNION to get joined output from 2 rows. A and B, following is the code.
"SELECT `ent_id` as `id`, `owner_id`, `category_id`, `ent_name` as `name`, `ent_details` as `details` FROM `A` WHERE `category_id` = '$cat'
UNION
SELECT `service_id` as `id`, `owner_id`, `category_id`, `service_name` as `name`, `service_details` as `details` FROM `B` WHERE `category_id` = '$cat'
The query works absolutely fine however I now want to know which output is from table A and which from B.
Is there a way to do this? If so how?
Thanks for your time. :)
Add a constant value to each select:
select 'table a' as source_table, ... from A where ...
union all
select 'table b' as source_table, ... from B where ...
Also, union eliminates duplicates between the two sets that form the union which union all doesn't. If there can be no duplicates you should use union all for better performance.

UNION ALL returning error when one sub-query finds no results?

This is my query:
SELECT UID, COUNT( * ) *100 AS Points
FROM `Visited`
WHERE UID = '25'
UNION ALL
SELECT UID, COUNT( * ) *1000 AS Points
FROM `Sites`
WHERE UID = '25'
UNION ALL
SELECT UID, COUNT( * ) *1000 AS Points
FROM `userTags`
WHERE UID = '25'
When I run it, and one of the subqueries finds no results I get:
#1048 - Column 'UID' cannot be null
I don't really understand the problem, running the subquery that gives no results alone works alright and displays:
UID | POINTS
NULL 0
However the big query won't unite it for some reason. What could be the reason?
---- EDIT
Also if the three subqueries give results the query works fine. The only problem is where there are no results in one of them.
It looks like there are no matching rows for UID = 25, however COUNT(*) still returns a row saying there are 0 matching rows. You can either remove the row by using an outer select where UID is not null, or more simply replace the NULL, like this:
SELECT UID, COUNT( * ) *100 AS Points
FROM `Visited`
WHERE UID = '25'
UNION ALL
SELECT ifnull(UID, '25'), COUNT( * ) *1000 AS Points
FROM `Sites`
WHERE UID = '25'
UNION ALL
SELECT UID, COUNT( * ) *1000 AS Points
FROM `userTags`
WHERE UID = '25';
Of course, you would replace the '25' with $uid for running from your code.
Do the same for the other tables too if you think there's a chance there are no matching rows

find mySQL duplicates and edit their specific fields

I have a table where the important fields are CompanyName and CompanyID. Right now there are a lot of rows with identical CompanyNames, but their CompanyIDs are unique. What I want to do is find all rows with exact CompanyNames and take one of their CompanyIDs (doesn't matter which) and apply it to all duplicates. I'm using this code to find all duplicates:
SELECT `CompanyName` , COUNT( `CompanyName` ) AS NumOccurrences
FROM `product_tbl`
GROUP BY `CompanyName`
HAVING (
COUNT( `CompanyName` ) >1
)
What do I need to add to accomplish what I want to do?
This should work:
UPDATE `product_tbl` `PA`,
(
SELECT `CompanyName`, `CompanyID`
FROM `product_tbl`
GROUP BY `CompanyName`
) `PB`
SET `PA`.`CompanyID` = `PB`.`CompanyID`
WHERE `PA`.`CompanyName` = `PB`.`CompanyName`;