SELECT * query, excluding columns - mysql

I have done allot of reading about this and it seems that isn't possible.
The thing is, since the amount of columns is dynamic i cant explicitly mention them. I put in aliases but the 'id' column keeps on appearing.
The CREATE doesnt work since there is 3 id columns in there, obiously.
(This query actually is ok, it works so dont evaluate it please)
CREATE TABLE merged as
SELECT *,
wuwebusers.id as wuwebusers_id,
jgwebusers_address.id as jgwebusers_address_id,
jgwebusers.id as jgwebusers_id
FROM wuwebusers
LEFT OUTER JOIN jgwebusers_address ON wuwebusers.id = jgwebusers_address.userid
LEFT OUTER JOIN jgwebusers ON wuwebusers.id = jgwebusers.userid
GROUP BY wuwebusers.id
EDIT:
question: how can i select every column except a few explicit ones. I know SELECT * isn't the correct way, since i am selecting all. I am asking for other way(s).
Since i have to do this a few times and the columns are dynamic and quite a few it isn't maintainable by explicitly writing every column name.

First you are doing a SELECT * Then adding columns as well. * is everything therefore you are getting mulitples of the same column. Those 3 ID's that you gave distinct names are being SELECTed again by the * in your query. Remove the * and type in the columns you need and you'll be fine.
CREATE TABLE merged as
SELECT
wuwebusers.id as wuwebusers_id,
jgwebusers_address.id as jgwebusers_address_id,
jgwebusers.id as jgwebusers_id ,
AllotherColumnsYouNeed as WhateverYouWantToCallthem
FROM wuwebusers
LEFT OUTER JOIN jgwebusers_address
ON wuwebusers.id = jgwebusers_address.userid
LEFT OUTER JOIN jgwebusers
ON wuwebusers.id = jgwebusers.userid
GROUP BY wuwebusers.id
/Edit\ If you changed your tables to not use the generic method of just labling a column ID in the first place you would also solve this problem. If you have a table name product for example call the ID column for that table ProductID. This will also solve your problem.

Related

SQL: How do add a prefix to column names in a JOIN?

I have sql query like this
SELECT * FROM phlegm WHERE JOIN mucus ON phlegm.id = mucus.id JOIN snot ON phlegm.id = snot.id
The problem is those tables contain several columns with identical names.
For example all 3 tables contain the column named test
If I retrieve the result of the query in PHP, then I will only get one value named test ($query->get_result()->fetch_object()->test;), because the other two get overwritten.
Is there some way to edit that query so that it adds a prefix to all columns from a table? For example, column test from table mucus would be referenced in the query as mucus_test and column test from phlegm would be phlegm_test.
One way would be doing
SELECT phlegm.test as phlegm_test, mucus.test as mucus_test FROM phlegm...
But I have a LOT of columns and tables and it would make the query longer than the Great Wall of China if I had to name each field one by one.
So is there some way to add the prefix en masse?
SELECT *, phlegm.test as phlegm_test, mucus.test as mucus_test FROM phlegm...
Used aliasing to retrieve all values associated from all three tables. if you want to reference only specific column do so by using the alias_name.column_name instead of p.*, where * means all columns belonging to table that the alias is associated with( ie. p refers to phlegm).
SELECT p.*, m.*, s.*
FROM phlegm p
JOIN mucus m ON p.id = m.id
JOIN snot s ON p.id = s.id;
I removed the WHERE from your original query above, not sure why it was there.

comparing two table columns in mysql results in duplicate

I have two tables, I've been trying to print the result from each but they are being duplicated. These are the two MySQL tables and the result. Notice the duplication.
The sql code for the project is:
SELECT * FROM savings,savtype WHERE cust_id=".$_SESSION['user']
I'm also looking for a work around this, in the meantime, id appreciate any assistance on this.
because you are not specifying how the two tables are related. You need to add that, either via an explicit ... JOIN ... (USING|ON)
SELECT
*
FROM
savings JOIN savtype USING (savtype_id)
WHERE
cust_id = ".$_SESSION['user']
or by providing the criteria in the where clause.
SELECT
*
FROM
savings, savtype
WHERE
savings.savtype_id = savtype.savtype_id AND
cust_id = ".$_SESSION['user']
As I understand from the screenshot you added, it makes joint between those tables, and what you probably want it left join from savings and savtype tables.
SELECT *
FROM `savings`
LEFT JOIN `savtype`
ON savings.savtype_id=savtype.savtype_id
where cust_id=".$_SESSION['user'] .";
Update if this did the trick,
You can learn more about left join here: https://www.w3schools.com/sql/sql_join_left.asp

MySQL query for finding rows that are in one table but not another

Let's say I have about 25,000 records in two tables and the data in each should be the same. If I need to find any rows that are in table A but NOT in table B, what's the most efficient way to do this.
We've tried it as a subquery of one table and a NOT IN the result but this runs for over 10 minutes and almost crashes our site.
There must be a better way. Maybe a JOIN?
Hope LEFT OUTER JOIN will do the job
select t1.similar_ID
, case when t2.similar_ID is not null then 1 else 0 end as row_exists
from table1 t1
left outer join (select distinct similar_ID from table2) t2
on t1.similar_ID = t2.similar_ID // your WHERE goes here
I would suggest you read the following blog post, which goes into great detail on this question:
Which method is best to select values present in one table but missing
in another one?
And after a thorough analysis, arrives at the following conclusion:
However, these three methods [NOT IN, NOT EXISTS, LEFT JOIN]
generate three different plans which are executed by three different
pieces of code. The code that executes EXISTS predicate is about 30%
less efficient than those that execute index_subquery and LEFT JOIN
optimized to use Not exists method.
That’s why the best way to search for missing values in MySQL is using a LEFT JOIN / IS NULL or NOT IN rather than NOT
EXISTS.
If the performance you're seeing with NOT IN is not satisfactory, you won't improve this performance by switching to a LEFT JOIN / IS NULL or NOT EXISTS, and instead you'll need to take a different route to optimizing this query, such as adding indexes.
Use exixts and not exists function instead
Select * from A where not exists(select * from B);
Left join. From the mysql documentation
If there is no matching row for the right table in the ON or USING
part in a LEFT JOIN, a row with all columns set to NULL is used for
the right table. You can use this fact to find rows in a table that
have no counterpart in another table:
SELECT left_tbl.* FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id =
right_tbl.id WHERE right_tbl.id IS NULL;
This example finds all rows in left_tbl with an id value that is not
present in right_tbl (that is, all rows in left_tbl with no
corresponding row in right_tbl).

mysql getting difference of 2 result sets

So I have two tables. One is called superIDs which has columns "superID BIGINT" and I have another one called mainIDs which has a column called "subid BIGINT". I know that mainIDS is a subset of superIDs. How can I see the rows that are ONLY in superID but not in mainIDs.
here is my attempt at a solution:
SELECT * FROM atlas_comparables.superIDs WHERE NOT EXISTS
(SELECT * FROM atlas_comparables.mainIDs);
However, this is returning me an empty set. Any help?
Try this
SELECT * FROM atlas_comparables.superIDs WHERE the_id_column NOT IN
(SELECT the_idcolumn_ofcomparable FROM tlas_comparables.mainIDs);
Note: the_id_column is in superIDs table
the_idcolumn_ofcomparable is in MainIdstable
If the ids only appear (at most) once in each table, then you can do this relatively easily with a left outer join:
select si.*
from atlas_comparables.superIDs si left join
atlas_comparables.mainIDs mi
on si.SuperID = mi.SubID
where mi.SubId is NULL;
If you are trying to compare all the columns (as except does in other databases), then you need a more complicated query, where you include all the columns on the on clause.

Populate 'temporary' columns with corresponding values during MySQL join query, also limit

I'm doing several MySQL joins to get template variables (i.e. custom fields) and their values (in MODX Evo but it's irrelevant - this is a general MySQL query).
I'm looking ideally to be able to create 2 temporary columns in order to use SORT BY in the query, or something to this effect. I'd like to populate the values for 'event_date' and 'event_featured' for their corresponding id's in these new columns - then I could then sort the results by these columns.
On a very related note I would like to limit the results to 20 for each unique id, not for each row as would happen if I added LIMIT- it would crop the below result to the . Can this be accomplished at the same time?
Anybody know how / if these are possible? Many thanks in advance.
Code and image of the results below:
SELECT DISTINCT
content.id, content.pagetitle, content.template , content.published,
templates.templatename,
tv_props.name,
tv_values.value
FROM `modx_site_content` AS `content`
LEFT JOIN `modx_site_templates` AS `templates` ON content.template=templates.id
LEFT JOIN `modx_site_tmplvar_templates` AS `template_tvs` ON templates.id=template_tvs.templateid
LEFT JOIN `modx_site_tmplvars` AS `tv_props` ON template_tvs.tmplvarid=tv_props.id
LEFT JOIN `modx_site_tmplvar_contentvalues` AS `tv_values` ON template_tvs.tmplvarid=tv_values.tmplvarid
WHERE templates.id=89
AND (
tv_props.name='event_featured'
OR tv_props.name='event_link_through'
OR tv_props.name='event_title'
OR tv_props.name='event_date'
OR tv_props.name='event_date_text'
OR tv_props.name='event_short_description'
OR tv_props.name='event_list_image'
);
Link to full-size image
You're going to need a couple of virtual tables, also known as subqueries, to retrieve these two properties of events from your name/value table. The generic name for this kind of query is a "pivot," for your information.
The mental knack is to think of the subquery as a virtual table which you can use in a surrounding query. The subquery for event_date looks like this, I believe.
SELECT content.id AS id,
tv_values.value AS event_date
FROM modx_site_content AS content
LEFT JOIN modx_site_templates AS templates
ON content.template=templates.id
LEFT JOIN modx_site_tmplvar_templates AS template_tvs
ON templates.id=template_tvs.templateid
LEFT JOIN modx_site_tmplvars AS tv_props
ON template_tvs.tmplvarid=tv_props.id
LEFT JOIN modx_site_tmplvar_contentvalues AS tv_values
ON template_tvs.tmplvarid=tv_values.tmplvarid
WHERE tv_props.name = 'event_date'
This little query produces a resultset that's a table relating content id to event date. I honestly don't understand your schema well enough to know if there's just one event date for each content id, so you might need to adjust this query to SELECT more columns. As you debug this, you should try out the subquery and make sure it's giving the results you hope for.
Then, when you're sure the subquery is OK, you join that subquery into your overall query, generically like so.
SELECT DISTINCT
content.id, event_date.event_date, templates.column,
table.column, table.colum, etc, etc
FROM modx_site_content AS content
LEFT JOIN table ON condition
LEFT JOIN (
SELECT content.id AS id,
tv_values.value AS event_date
FROM modx_site_content AS content
LEFT JOIN modx_site_templates AS templates
ON content.template=templates.id
LEFT JOIN modx_site_tmplvar_templates AS template_tvs
ON templates.id=template_tvs.templateid
LEFT JOIN modx_site_tmplvars AS tv_props
ON template_tvs.tmplvarid=tv_props.id
LEFT JOIN modx_site_tmplvar_contentvalues AS tv_values
ON template_tvs.tmplvarid=tv_values.tmplvarid
WHERE tv_props.name = 'event_date'
) AS event_date ON event_date.id = content.id
LEFT JOIN etc, etc, etc.
WHERE etc etc etc
Do you see how that goes? You can use tablename AS table or (some query) AS table interchangeably. You can also define a VIEW in your schema that provides the same data, and name it in your query. That's a handy way to make your queries less hairy.
By the way, you'll boost performance if you change
AND (
tv_props.name='event_featured'
OR tv_props.name='event_link_through'
OR tv_props.name='event_title' etc )
to
AND tv.props.name IN ('event_featured',
'event_link_through',
'event_title', etc)
You've probably noticed I'm a bit of a stickler for indentation in SQL queries. I find this helpful; I often find mistakes while I'm fixing up the indentation. Your practice may vary.