Performing a custom SQL query - mysql

I want to select all those rows in table A where column x's value is present in table B's column y.
I am new to writing SQL queries have have tried using different combinations of SELECT statement, COUNT function and WHERE clause since are a really long time, but was unable to do so.
Is it possible to do this using plain SQL queries or is something complex like procedure needed?

A typical method is exists:
select a.*
from a
where exists (select 1
from b
where b.y = a.x
);

Related

MySQL use subquery from FROM in WHERE

I have a question about MySQL. My script looks like this :
SELECT *
FROM (subQuery) AS q1
WHERE
(SELECT something
FROM q1
WHERE id = q1.id-1) = x;
My problem is that in the last subquery the table q1 is unknown. How can I solve this?
You can't compare rows in the results. The best you could do is duplicate the subquery, call it q1b for example, and join it to q1 on q1.id - 1 = q1b.id; then in the where have something like q1b.something = x (though that can be in the ON as well)
There is also some possibilities with temp tables; but you still need the two joins, or maybe a correlated subquery in the where would work. ... if stored in a true TEMPORARY table, not just some "dummy" table you drop after, you'll need two copies. You can't use the same TEMPORARY table twice in the same query.

Access columns within exists clause

select *
from AllUK
where exists (select * from AllCompanies where replace(AllUK.mobile,' ','')=replace(AllCompanies.mobile,' ',''))
I need to include the columns from the AllCompanies table in to my first select. How can I do that?
select *
from AllUK a
join AllCompanies b
on a.mobile = b.mobile
exists is a boolean operation, so the clause you have above will always return all the results if there any records that can be joined accross the 2 tables. It's hard to tell what you're really trying to achieve.
Also, putting string operations on columns within exists and joins is not best practice because the compiler has to do the operation on every row & column at run time. Might be better to create a temp table to hold the replaced values and then join on that.

Subquery for fetching table name

I have a query like this :
SELECT * FROM (SELECT linktable FROM adm_linkedfields WHERE name = 'company') as cbo WHERE group='BEST'
Basically, the table name for the main query is fetched through the subquery.
I get an error that #1054 - Unknown column 'group' in 'where clause'
When I investigate (removing the where clause), I find that the query only returns the subquery result at all times.
Subquery table adm_linkedfields has structure id | name | linktable
Currently am using MySQL with PDO but the query should be compatible with major DBs (viz. Oracle, MSSQL, PgSQL and MySQL)
Update:
The subquery should return the name of the table for the main query. In this case it will return tbl_company
The table tbl_company for the main query has this structure :
id | name | group
Thanks in advance.
Dynamic SQL doesn't work like that, what you created is an inline-view, read up on that. What's more, you can't create a dynamic sql query that will work on every db. If you have a limited number of linktables you could try using left-joins or unions to select from all tables but if you don't have a good reason you don't want that.
Just select the tablename in one query and then make another one to access the right table (by creating the query string in php).
Here is an issue:
SELECT * FROM (SELECT linktable FROM adm_linkedfields WHERE name = 'company') as cbo
WHERE group='BEST';
You are selecting from DT which contains only one column "linktable", then you cant put any other column in where clause of outer block. Think in terms of blocks the outer select is refering a DT which contains only one column.
Your problem is similar when you try to do:
create table t1(x1 int);
select * from t1 where z1 = 7; //error
Your query is:
SELECT *
FROM (SELECT linktable
FROM adm_linkedfields
WHERE name = 'company'
) cbo
WHERE group='BEST'
First, if you are interested in cross-database compatibility, do not name columns or tables after SQL reserved words. group is a really, really bad name for a column.
Second, the from clause is returning a table containing a list of names (of tables, but that is irrelevant). There is no column called group, so that is the problem you are having.
What can you do to fix this? A naive solution would be to run the subquery, run it, and use the resulting table name in a dynamic statement to execute the query you want.
The fundamental problem is your data structure. Having multiple tables with the same structure is generally a sign of a bad design. You basically have two choices.
One. If you have control over the database structure, put all the data in a single table, linktable for instance. This would have the information for all companies, and a column for group (or whatever you rename it). This solution is compatible across all databases. If you have lots and lots of data in the tables (think tens of millions of rows), then you might think about partitioning the data for performance reasons.
Two. If you don't have control over the data, create a view that concatenates all the tables together. Something like:
create view vw_linktable as
select 'table1' as which, t.* from table1 t union all
select 'table2', t.* from table2 t
This is also compatible across all databases.

Select Left(columnA,2) or right(columnA,1)

Is there a way in MySql to use an either or in a select column. For instance
select left(columnA,2) or right(columnA,1) as columnAlias, sum(columnB)
from table
where ((left(columnA,2) in ('aa','bb','cc')) or (right(columnA,1) in ('a,','b','c')))
group by columnAlias
what I have is a table where either the first 2 characters of the column or the last character of the column indicates the facility. I need to sum the values by facility. A union gets me part way there then I could loop through the resulting dataset and sum things up in the code (or do a stored proc to return the sums), but I am wondering if there is a way to just get it from the query.
I've tried using the union query as an on the fly temp table and doing the select and group on that but if there are no records returned from either of the select statments then it throws a "column columnA cannot be null error.
Also tried with the syntax above, but not getting the results I am expecting. Any other ways to do this through the query?
using a CASE would prob be your best bet here.
http://dev.mysql.com/doc/refman/5.0/en/case-statement.html

multi row "dual" table in mysql/sql

This is an extension of the "dual" table concept (temporary table created on the fly for one query and discarded straight after)
I am trying to join a multi row dual table with another one, so as to avoid to have to run the same query several times with different parameters, using 1 statement.
One of the issue I am having is that union is very slow for dual tables, and I am unaware of any more efficient way to accomplish the following. (100 ms when joining 50 dual together)
SELECT
b.id,
b.ref_unid,
a.date
FROM
(
SELECT
'b8518a84-c501-11dd-b0b6-001d7dc91168' as unid,
'2010-01-05' as date
UNION
SELECT
'b853a1f2-c501-11dd-b0b6-001d7dc91168',
'2010-01-06'
UNION
SELECT
'b8557bd0-c501-11dd-b0b6-001d7dc91168',
'2010-01-07'
/* ... */
) as a
join other_table b
ON
b.ref_unid = a.unid
Is there another way of accomplishing this goal?
Is there any syntax similar to that of insert into values statement that would accomplish that goal, such as:
SELECT
unid,
id
FROM
(
WITH (unid, date) USING VALUES
(
('b8518a84-c501-11dd-b0b6-001d7dc91168','2010-01-05'),
('b853a1f2-c501-11dd-b0b6-001d7dc91168','2010-01-06'),
('b8557bd0-c501-11dd-b0b6-001d7dc91168','2010-01-07'),
/* ... */
)
) as a
join other_table b
ON
b.ref_unid = a.unid
I'm looking for a 1-statement solution. Multiple trips to the database aren't possible.
There's no other convention I'm aware of that's available in MySQL to construct a derived table in a single statement. If this dealt with a single column, at ~50 values it could be converted to use an IN clause.
The best performing approach is to load the data into a table of one form or another -- in MySQL, for a temporary use I'd recommend using the MEMORY engine. At ~50 tuples, I have to wonder why the data isn't already in the database...