find the output mysql query - mysql

I have a table name T1 having only one Column name Col1 having rows –
Col1
a
b
c
And another table name T2 also having only one Column name Col1 having rows –
Col1
x
y
z
Now I want record like
Col1--Col2
a------x
b------y
c------z
I am using mysql.
Thanks in advance!!

create table T1(col1 varchar(10));
insert T1 values ('a'),('b'),('c');
create table T2(col2 varchar(10));
insert T2 values ('x'),('y'),('z');
select A.col1, B.col2 from
(select #r:=#r+1 rownum, col1 from (select #r:=0) initvar, T1) A,
(select #s:=#s+1 rownum, col2 from (select #s:=0) initvar, T2) B
where A.rownum=B.rownum
Because there is no ORDER BY clause, you are depending on luck and convention for the row numbering to be according to the order inserted. It may not always be the case.

In your example, if you want to join the tables to get row results like this:
Row 1 - A,X
Row 2 - B,Y
Row 3 - C,Z
..then you will have to add a common field that you can JOIN the two tables on.
If you want to be able to return results from both tables like this:
Row 1 - A
Row 2 - B
Row 3 - C
Row 4 - X
Row 5 - Y
Row 6 - Z
.. then you will need to use a UNION:
(SELECT Col1 FROM T1) UNION (SELECT Col1 FROM T2)

Related

Checking for a one-to-one correlation of data with MySQL

Suppose I have data containing two columns I am interested in. Ideally, the data in these is always in matching sets like this:
A 1
A 1
B 2
B 2
C 3
C 3
C 3
However, there might be bad data where the same value in one column has different values in the other column, like this:
D 4
D 5
or:
E 6
F 6
How do I isolate these bad rows, or at least show that some of them exist?
You can use exists:
select t.*
from t
where exists (select 1 from t t2 where t2.col1 = t.col1 and t2.col2 <> t.col2);
If you just want the col1 values that have non-matches, you can use aggregation:
select col1, min(col2), max(col2)
from t
group by col1
having min(col2) <> max(col2);
Using MIN and MAX as analytic functions we can try:
WITH cte AS (
SELECT t.*, MIN(col2) OVER (PARTITION BY col1) AS min_col2,
MAX(col2) OVER (PARTITION BY col1) AS max_col2
FROM yourTable t
)
SELECT col1, col2
FROM cte
WHERE min_col2 <> max_col2;
The above approach, while seemingly verbose, would return all offending rows.

Get Sum of rows of SQL query that satisfies multiple criteria

I have a table and I am trying to get the sum of Col A to 2 decimal places of all rows (there is an id column ID) that satisfies the following:
1) There is another row with a matching Col B
2) It has an unique pair of the values in Col C and Col D
Try this:
SELECT ROUND(SUM(ColA), 2) AS ColA_Sum
FROM datatable t
WHERE EXISTS (
SELECT 1
FROM datatable t2
WHERE t2.ID <> t.ID -- Another row must have different id
AND t2.ColB = t.ColB -- Matching Column B
)
AND EXISTS (
SELECT 1
FROM datatable t3
WHERE t3.ColC = t.ColC -- Same Column C
AND t3.ColD = t.ColD -- Same Column D
HAVING COUNT(*) = 1 -- Only 1 row with such values
)
I think it might be as simple as:
SELECT ROUND(SUM(t.cola), 2) AS cola_sum
FROM t
WHERE cola = colb
AND NOT EXISTS
(SELECT 1
FROM t t2
WHERE t2.colc = t.colc
AND t2.cold = t.cold
GROUP BY colc, cold
HAVING COUNT(*) > 1)
Check out the test here: http://rextester.com/BSVW57900

Query to match different values in one column that have same value in a separate column

I am trying to write a query that will take two different values in column b and then compare it with column c to determine if the two values in column b share the same value in Column C. However i also need column A in the output as well.
For example
Column A Column B Column C
Test 1 x 12345
Test 2 y 12345
Test 3` A 12344
Test 4 D 12342
Desired Output
Column A Column B Column C
Test 1 x 12345
Test 2 y 12345
Any help would be great
I'm not sure if the values in ColumnB are significant. This query finds values of ColumnC that are repeated and then returns those rows:
select * from T where ColumnC in (
select ColumnC from T
group by ColumnC
having count(*) > 1 /* or maybe count(distinct ColumnB) > 1 */
)
try this
SELECT a.* FROM table a join table b on a.c=b.c and a.b<>b.b
The query doesn't take into account rows that have same values in c and b column.
You can add DISTINCT in the select if needed.
You can perform a JOIN like below. See a demo fiddle http://sqlfiddle.com/#!9/da525/4
select t.*
from tbl1 t join tbl1 s on t.`Column C` = s.`Column C`
and t.`Column B` <> s.`Column B`;
(OR) Using WHERE EXISTS
select t.*
from tbl1 t
where exists ( select 1 from tbl1
where `Column C` = t.`Column C`
and `Column B` <> t.`Column B`);

mysql - Referencing alias for calculation after UNION

Ok, here's the query (pseudo-query):
SELECT *, (t1.field + t2.field) as 'result', (t1.field * t2.field) as result2 from((select as t1 limit 1) UNION ALL (select as t2 limit 1))
I need both rows returned, then do the math on the two fields into the result aliases. I know it's not graceful, but I have to kludge two queries together (the first is the union, and the second is the math)
So, how do I reference and use those two inner aliases? The inner aliases aren't accessible to the outer select.
I have a suspicion there's an obvious solution here that my brain is missing.
When you union two statements together your result is a single resultset. What you'll build:
FROM
(
(SELECT f1, f2 FROM table1 LIMIT 1)
UNION
(SELECT g1, g2 FROM table2 LIMIT 1)
) derived_table_1
This will give you a single result set named derived_table_ with two fields named f1 and f2 respectively. There will be two rows, one from your first SELECT statement and another from your second. The table aliases that you assigned inside your UNION query are no longer referencable. They exist only within their own SELECT statements.
If you have a relationship between Table1 and Table2 then you want a JOIN here:
SELECT
t1.f1 + t2.g1 as result1,
t1.f2 + t2.g2 as result2,
FROM
table1 as t1
INNER JOIN table2 as t2 ON
t1.f1 = t2.g1
If, instead no relationship exists, then you are probably looking for you original, and kludgy, union with a SUM in the SELECT:
SELECT
sum(derived_table_1.f1) as result,
sum(derived_table_1.f2) as result2
FROM
(
(SELECT f1, f2 FROM table1 LIMIT 1)
UNION
(SELECT g1, g2 FROM table2 LIMIT 1)
) derived_table_1
Editted to add a SQLFIDDLE with the last example: http://sqlfiddle.com/#!2/c8707/10
The column names or aliases for the result of a UNION are always determined by the first query. The column names or aliases defined in the subsequent queries of the union are ignored.
Demo:
mysql> create table foo ( a int, b int, c int );
mysql> insert into foo values (1,2,3);
mysql> create table bar (x int, y int, z int);
mysql> insert into bar values (4,5,6);
mysql> select a, b, c from (select a, b, c from foo union select x, y, z from bar) as t;
+------+------+------+
| a | b | c |
+------+------+------+
| 1 | 2 | 3 |
| 4 | 5 | 6 |
+------+------+------+
mysql> select x from (select a, b, c from foo union select x, y, z from bar) as t;
ERROR 1054 (42S22): Unknown column 'x' in 'field list'

Slow query on update using select count(*)

I have to count how many times a number from table2 occurs between the number in range table2.a and table2.b
i.e. we wanna know how many times we have this : a < start < b
I ran the following query :
UPDATE table2
SET occurrence =
(SELECT COUNT(*) FROM table1 WHERE start BETWEEN table2.a AND table2.b);
table2
ID a b occurrence
1 1 10
2 1 20
3 1 25
4 2 30
table1
ID start col1 col2 col3
1 1
2 7
3 10
4 21
5 25
6 27
7 30
table2 as
3 indexes on a, b and occurrence
1567 rows (so we will SELECT COUNT(*) over table2 1567 times..)
ID column as PK
table1 as
1 index on start
42,000,000 rows
Column start was "ordered by column start"
ID column as PK
==> it took 2.5hours to do 2/3 of it. I need to speed this up... any suggestions ? :)
You could try to add the id column to the index on table 1:
CREATE INDEX start_index ON table1 (start,id);
And rewrite the query to
UPDATE table2
SET occurrence =
(SELECT COUNT(id) FROM table1 WHERE start BETWEEN table2.a AND table2.b);
This is called "covering index": http://www.simple-talk.com/sql/learn-sql-server/using-covering-indexes-to-improve-query-performance/
-> The whole query on table 1 can be served through the data in the index -> no additional page lookup for the actual record.
Use a stored procedure. Keep the result from COUNT in a local variable, then use it to run the UPDATE query.
I will do this
// use one expensive join
create table tmp
select table2.id, count(*) as occurrence
from table1
inner join table1
on table1.start between table2.a and table2.b
group by table1.id;
update table2, tmp
set table2.occurrence=tmp.occurrence
where table2.id=tmp.id;
I think count(*) makes the database read the data rows when in your case it only needs to read the index. Try:
UPDATE table2
SET occurrence =
(SELECT COUNT(1) FROM table1 WHERE start BETWEEN table2.a AND table2.b);