How to rewrite this SELECT query - mysql

I've been left with some code that looks like this:
SELECT DISTINCT ee.* FROM exp_extensions ee WHERE enabled = 'y'
Our db admin is screaming about the select all, and wants us to grab all the individual fields separately. I've never seen a SELECT DISTINCT * before; how would I rewrite that?
Option 1:
SELECT DISTINCT ee.extension_id, ee.class, ee.method, ee.hook, ee.settings, ee.priority, ee.version, ee.enabled FROM exp_extensions ee WHERE enabled = 'y'
Option 2:
SELECT DISTINCT (ee.extension_id, ee.class, ee.method, ee.hook, ee.settings, ee.priority, ee.version, ee.enabled) FROM exp_extensions ee WHERE enabled = 'y'
Or some other way entirely?

There is no difference between Option 1 or Option 2. Say you have a table that has one column col1 that has one row. All of these produce the same result:
SELECT DISTINCT * FROM t1
SELECT DISTINCT col1 FROM t1
SELECT DISTINCT (col1) FROM t1
SELECT * FROM t1
SELECT col1 FROM t1
SELECT (col1) FROM t1
All the * does is essentially expand to all available columns on the table.

Related

Alternative to except in MySQL

I must write a Query like this in MySQL:
SELECT *
FROM Tab1
EXCEPT
SELECT *
FROM Tab1
WHERE int_attribute_of_Tab1>0
but MySQL doesn't support the keyword EXCEPT.
Is there a standard mode to use correctly another operator that simulate the except in MySQL?
You could use NOT IN
SELECT *
FROM Tab1
WHERE id NOT IN (
SELECT id
FROM Tab1
WHERE int_attribute_of_Tab1>0
)
Try this
SELECT *
FROM Tab1
WHERE [....] NOT EXISTS
(SELECT *
FROM Tab1
WHERE int_attribute_of_Tab1>0)
A couple of definitions
SqlServer https://learn.microsoft.com/en-us/sql/t-sql/language-elements/set-operators-except-and-intersect-transact-sql EXCEPT
Returns any distinct values from the query to the left of the EXCEPT operator that are not also returned from the right query.
PLsql https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries004.htm MINUS
statement combines results with the MINUS operator, which returns only unique rows returned by the first query but not by the second
A pedantic translation to mysql would be
SELECT distinct t1.*
FROM Tab1 as t1
left outer join
(SELECT *
FROM Tab1
WHERE int_attribute_of_Tab1>0) as t2 on t1.id = t2.id
where t2.id is null;
Assuming there is an id column, And I wouldn't like to use distinct on a lot of columns.
You can use multiple NOT IN operators combined with AND operators for multiple columns.
For example:
SELECT col1, col2 FROM table1 WHERE col1 NOT IN(SELECT col1 FROM table2) AND col2 NOT IN(SELECT col2 FROM table2)...;
Since MySQL version 8.0.31 update, the EXCEPT operator has become available to use in this DBMS. If you are allowed to update your MySQL version, you are free to use the notation:
SELECT * FROM Tab1
EXCEPT
SELECT * FROM Tab1
WHERE int_attribute_of_Tab1>0
If Tab1 has a primary key (f.e. ID) then you could use a NOT EXISTS to itself like this :
SELECT *
FROM Tab1 AS t1
WHERE NOT EXISTS (
SELECT 1
FROM Tab1 AS t2
WHERE t2.ID = t1.ID
AND t2.int_attribute_of_Tab1 > 0
)
But it's kinda pointless in this case.
And it's not what an EXCEPT/MINUS tries to do.
(excluding identical rows)
The question's query with the EXCEPT uses the same table twice.
So reversing that WHERE criteria on Tab1 would give the same results.
SELECT *
FROM Tab1
WHERE (int_attribute_of_Tab1 <= 0 OR int_attribute_of_Tab1 IS NULL)
If it were 2 different tables then this
SELECT t1col1, t1col2, t1col3
FROM Table1
EXCEPT
SELECT t2col4, t2col5, t2col6
FROM Table2
WHERE int_attribute_of_Tab1 > 0
Could be replaced by comparing each selected column
SELECT DISTINCT t1col1, t1col2, t1col3
FROM Table1 AS t1
WHERE NOT EXISTS (
SELECT 1
FROM Table1 AS t2
WHERE t2.t2col4 = t1.t1col1
AND t2.t2col5 = t1.t1col2
AND t2.t2col6 = t1.t1col3
AND t2.int_attribute_of_Tab1 > 0
)

Select and order by an union

Is it possible to:
SELECT * FROM table1 , table2 ORDER BY (a UNION)
I tried that but doesn't work.
I looked on Google for some answers but got nothing and I don't know how to look anymore, what to search so this is my last solution: ask here. Maybe one of you knows a clause I don't and would help in my case. I don't know how else to think this query...
The union is made between two columns from two tables (or more). So i want to order every possible row by this new column made with union. Something like (so this will be generic) :
SELECT * FROM table1 , table2 ORDER BY ((SELECT col1 AS col FROM table1) UNION ALL (SELECT col2 AS col FROM table2) ORDER BY col DESC);
Try this query like that :-
SELECT * FROM(
SELECT * FROM table1
UNION
SELECT * FROM table2
) as tab ORDER BY col_name
If you want to do the union and then order, you can do:
select t1.*
from table1 t1
union
select t2.*
from table2 t2
order by a;
Notes:
Use union all rather than union, unless you specifically want to incur the overhead of removing duplicates.
The use of * implies that the two tables have the same columns in the same order (and compatible types).

How to get values from one table column, concatenate them with a string and insert them in another table?

How to:
Get values from table1.column1 (e.g. abc)
table1.column1=abc
Concatenate them with certain fixed strings, e.g.
xxx
yyy
zzz
Insert the results as separate rows in table2.column2. The final result should be rows with values like this:
table2.column2=abc_xxx
table2.column2=abc_yyy
table2.column2=abc_zzz
(table2 has a connecting column indicating to which ID the table2.column2 record corresponds in case this matters)
Repeat this process for all records in table1.column1 which have table1.item_id > 100
EDIT: For certain convenience I would like the final result rows sequence to look like:
source1_xxx
source1_yyy
source1_zzz
source2_xxx
source2_yyy
source2_zzz
and not like:
source1_xxx
source2_xxx
source1_yyy
source2_yyy
source1_zzz
source2_zzz
If I understand you correctly, you want N (e.g. 3) entries for every existing row in Table1. If so, you can CROSS JOIN Table1 to a projection of the values, like so:
INSERT INTO Table2(column2)
SELECT CONCAT(t1.column1, '_', x.col)
FROM Table1 t1
CROSS JOIN
(SELECT 'xxx' AS col
UNION
SELECT 'yyy'
UNION
SELECT 'zzz') x;
SqlFiddle here
Edit
The query was updated to be cognaisant of the ordering and filtering requirements as well:
INSERT INTO Table2(column2)
SELECT CONCAT(t1.column1, '_', x.col)
FROM Table1 t1
CROSS JOIN
(SELECT 'xxx' AS col
UNION
SELECT 'yyy'
UNION
SELECT 'zzz') x
WHERE t1.ID > 100
ORDER BY t1.column1 ASC, x.col ASC;
With an updated SqlFiddle
Modifying the answer.
Credit goes to the StuartLC ..he is right, you would need to use cross join
INSERT INTO Table2(column2)
SELECT CONCAT(t1.column1, '_', x.col)
FROM Table1 t1
CROSS JOIN
(SELECT 'xxx' AS col
UNION
SELECT 'yyy'
UNION
SELECT 'zzz') x;
is this what u want
insert into table2(column2)
select concat(col1,'_','xxx') from table1
union
select concat(1col1,'_','yyy') from table1
union
select concat(col1,'_','zzz') from table1
else keep this entire select statemnts in aview and use it in the insert statement
create view abc
as
select concat(col1,'_','xxx') from table1
union
select concat(1col1,'_','yyy') from table1
union
select concat(col1,'_','zzz') from table1
then
insert into table2(column2) select * from abc

Many selects from different tables and not show result if nothing found

I have many tables and some of them have column 'Item'. I want to make easy query,which allow me to check in which table or tables i can find item with number which i want.
I have read some info about variable and made this:
SET #Item_id =(there i put number) ;
select * from table1 where item=#Item_id;
select * from table2 where item=#Item_id;
select * from table3 where item=#Item_id;
select * ...(other tables)
Problem is my DBMS will show tabs with result for each table and it doesn't matter if search was successful or not.
How can i update code to show me tables only with results ?
SET #Item_id = 29434;
SELECT
(select distinct item from creature_loot_template where item=#Item_id) as table1
(select distinct item from gameobject_loot_template where item=#Item_id) as table2
(select distinct item from item_loot_template where item=#Item_id) as table3
This may not do exactly what you want, but for instances like this, I usually use the union option to dump the results from all the queries into one single table. To show which query or source table it came from, I make a fake column with a string constant.
SET #Item_id =(there i put number) ;
select 'table1', * from table1 where item=#Item_id union
select 'table2', * from table2 where item=#Item_id union
select 'table3', * from table3 where item=#Item_id;
You can try Something like this:
SET #Item_id =(the Id you want to check) ;
SELECT
(select distinct item from table1 where item=#Item_id) as table1
(select distinct item from table2 where item=#Item_id) as table2
(select distinct item from table3 where item=#Item_id) as table3
...
That way, you should have an input like this:
table1 table2 table3
null null item
Therefore you will know in which table you found your item.

Get data from multiple SELECT sub-queries for reporting from MySQL database

I'm trying to achieve is to create one complex query consisting of a few sub-queries. The idea is to give it to a business person to run on a weekly basis to pull reporting data.
The effect would be similar to the query below, where all data from many tables are displayed in one result.
select * from table1, table2, table3
So I need something like, but it's not working.
select
(select * from table1 where ...... ) as table1,
(select * from table2 where....... ) as table2
Manually, I could run the sub-queries separately, then manually append the results into one big excel sheet. But I want to make it easier for the business person to do this, and minimize errors.
Is this possible in MySQL?
The reason for this is I'm converting a legacy Oracle PIVOT SQL statements into the MySQL equivalence, and the sub-queries are pretty complex.
I can provide the Oracle SQL if needed.
Much appreciated as always.
After some fiddling around:
select * from
(select * from table1 where survey_user_id=4 ) as T1
,
(select * from table2 where survey_field_type_id=100 ) as T2
,
(select * from table3 ) as T3
If i understand you correctly you just need UNION :D
(SELECT column1 AS name1, column2 AS name2 FROM table1 WHERE ...... )
UNION
(SELECT column3 AS name1, column4 AS name2 FROM table2 WHERE ...... )
UNION
....
As mentioned bellow in comment,
columns need to have the same name (you can use aliases for it) and stay in the same order.
select main.*,
(select col from tbl1 where tbl1.id=main.id) as col1,
(select col from tbl2 where tbl2.id=main.id) as col2,
(select col from tbl3 where tbl3.id=main.id) as col3
from master as main