Table A
id name age
-- ---- ---
1 a 9
2 b 11
3 c 10
Table B
id name address
-- ------ -------
1 aa abc
1 aa efg
3 bb hij
Table C
id name address age
-- ------ ------- ---
1 aa abc 9
1 aa efg 9
2 NULL NULL 11
3 bb hij 10
how can i join this unrelated table become like this :
Table D
id name address age
--- ---- ------- ----
1 a null 9
2 b null 11
3 c null 10
1 aa abc null
1 aa efg null
3 bb hij null
1 aa abc 9
1 aa efg 9
2 NULL NULL 11
3 bb hij 10
if you have some refference to read how to create controller, model and search model, i will be so glad..thank you very much
Looking to you sample seems you need an union between the 3 tables
$sql = "select id, name, address, age
from table_c
union all
select id, name, address, null
from table_b
union all
select id, name, null, age
from table_a;";
and you could use a raw SQL command to retrieve the query rows
$connection = Yii::$app->getDb();
$command = $connection->createCommand($sql);
$result = $command->queryAll();
In $result you obtain an array and each array element is an array representing a row of data.
Related
I has Join table, and result is like this
IDA IDB QTY
A 3 1
A 4 1
A 5 1
B 3 1
B 4 1
C 3 2
D 3 2
E 3 1
F 4 1
G 3 1
G 4 1
G 5 1
H 3 3
H 4 3
H 5 3
i'm confused how to count the IDA who has same Condition of IDB and QTY together.
So what i want is:
Combination of IDB - QTY
(3-1, 4-1, 5-1) = 2 from IDA (A and G)
(3-1) = 1 from IDA (E)
(3-2) = 2 from IDA (C and D)
So basically i want count of IDA who has same IDB and QTY Combination. What Query should i do? i still don't get how making query for this logic, thank you.
Edit :
What i want is the result in one query, i will not making manually Where condition of IDB-QTY Combination. (so basically the result is not from Where condition)
You can use aggregating with using group_concat() function
select group_concat( ida order by ida ) as grouped_letters, count(*) as count
from
(
select ida, count( idb - qty ) as ct, sum( idb - qty ) as sm
from tab
group by ida
) q
group by ct, sm
order by ida;
+---------------+-----+
|grouped_letters|count|
+---------------+-----+
| B | 1 |
| C,D | 2 |
| E | 1 |
| F | 1 |
| A,G | 2 |
| H | 1 |
+---------------+-----+
Demo
Lets say I have table
teach_subject(teacher_id, subject_id, min_grade_of_school, max_grade_of_school, color_in_timetable)
Example data:
teacher_id subject_id min_grade_of_school max_grade_of_school color_in_timetable
1 2 1 4 #A00
1 2 5 6 #0A0
1 2 9 11 #00A
1 3 1 7 #AA0
It is not allowed that min_grad_of_school > max_grad_of_school, but maybe they are equal.
It is also not allowed that for a given tuple (t_id_new, s_id_new, min_grade_new, max_grade_new, color_new) there exists an other tuple (t_id, s_id, min_grade, max_grade, color) in the table holding
t_id_new = t_id and s_id_new = s_id and
( min_grade <= min_grade_new <= max_grade or min_grade <= max_grade_new <= max_grade )
So for the given example a new tuple like (1,2,6,11,#FFF) or (1,2,2,7,#FFF) is not possible.
So far no problem.
Now I want to ignore the color and join the "connected" rows, i.e. if teacher 1 teaches subject 2 from the 1st grade to the 4th grade, and from the 5th grade to the 6th grade, you can also say he teaches subject 2 from 1st to 6th grade.
So I want to "join" the tuples (1,2,1,4) and (1,2,5,6) to (1,2,1,6) but i dont want to join (1,2,4,5) and (1,2,9,11), since ther is a (integer) gap between 5 and 9.
I just have no idea if there is a way to do this with MySQL. At the moment I just select all the data an edit the selected data with PHP. Is there a MySQL way to directly select what I want or should stick to PHP?
Edit
Example result (for the above example data) :
teacher_id subject_id min_grade_of_school max_grade_of_school color_in_timetable
1 2 1 6 #A00
1 2 9 11 #00A
1 3 1 7 #AA0
Edit 2
Maybe can use a stored procedure?
DROP TABLE IF EXISTS teach_subject;
CREATE TABLE teach_subject
(teacher_id INT NOT NULL
,subject_id INT NOT NULL
,min_g INT NOT NULL
,max_g INT NOT NULL
,color_in_timetable CHAR(4) NOT NULL
,PRIMARY KEY(teacher_id,subject_id,min_g)
);
INSERT INTO teach_subject VALUES
(1,2,1,4,'#A00'),
(1,2,5,6,'#0A0'),
(1,2,9,11,'#00A'),
(1,3,1, 7,'#AA0');
SELECT a.teacher_id
, a.subject_id
, a.min_g
, MIN(c.max_g) max_g
, a.color_in_timetable
FROM teach_subject a
LEFT
JOIN teach_subject b
ON b.teacher_id = a.teacher_id
AND b.subject_id = a.subject_id
AND b.min_g = a.max_g - 1
LEFT
JOIN teach_subject c
ON c.teacher_id = a.teacher_id
AND c.subject_id = a.subject_id
AND c.min_g >= a.min_g
LEFT
JOIN teach_subject d
ON d.teacher_id = a.teacher_id
AND d.subject_id = a.subject_id
AND d.min_g = c.max_g + 1
WHERE b.teacher_id IS NULL
AND c.teacher_id IS NOT NULL
AND d.teacher_id IS NULL
GROUP
BY a.teacher_id,a.subject_id,a.min_g;
+------------+------------+-------+-------+--------------------+
| teacher_id | subject_id | min_g | max_g | color_in_timetable |
+------------+------------+-------+-------+--------------------+
| 1 | 2 | 1 | 6 | #A00 |
| 1 | 2 | 9 | 11 | #00A |
| 1 | 3 | 1 | 7 | #AA0 |
+------------+------------+-------+-------+--------------------+
I have a sample data with table is test
name | catid | date
------------
abc | 1
def | 2
ghi | 1
jkl | 2
mno | 1
pqr | 3
And my query
SELECT * FROM test WHERE catid = 1 AND catid = 2 AND catid = 3 ORDER BY date DESC
How to get value with result is
name | catid
------------
abc | 1
def | 2
pqr | 3
SELECT a.*
FROM TableName a
INNER JOIN
(
SELECT catid, MAX(DATE) max_date
FROM tableName
GROUP BY catID
) b ON a.catID = b.catID AND
a.date = b.max_date
SELECT name, catid FROM test WHERE catid IN (1, 2, 3) GROUP BY catid
I think you need the IN operator which is simplier than catid = X OR catid... (and you need OR, not AND)
Based on your desired output, this might be the query:
select catid, min(name)
from yourtable
where catid between 1 and 3
group by catid
But it's hard to know what you want based on the info provided in your question.
I simplified the table so it is easier to understand.
I have a table with groups and a group exists of multiple values. Here is the table:
VALUE | GROUP
A | 1
B | 1
A | 2
C | 2
B | 3
A | 4
B | 4
A | 5
B | 5
C | 5
I want to give values to my query wich I programmatically build and find the exact group that matches to these values.
For example if I give value A and B to my query I want as a result group 1 and 4
A ---------------> null
A and B ----------> 1 and 4
A , B and C ------> 5
B ---------------> 3
A and C ----------> 2
C ----------------> null
You can use a query like the following (assuming value,group pairs unique):
select `GROUP`
from MyTable
group by `GROUP`
having count(`VALUE`) = count(case when `VALUE` IN ('a','b') then 1 end)
and count(case when `VALUE` IN ('a','b') then 1 end) = #Count;
Where ('a','b') would be the list of values you are testing for, and #Count would be the count of different values in your check set (2 in this case).
Demo: http://www.sqlfiddle.com/#!2/78def/13
I have two tables that I need to join. These are:
art
id | art
--------
1 | A
2 | B
3 | C
4 | D
5 | E
6 | F
7 | G
8 | H
9 | I
and
Sess
artid | sessid
--------------
1 | 1
2 | 1
3 | 1
4 | 1
1 | 2
4 | 2
5 | 2
6 | 2
1 | 3
2 | 3
7 | 3
4 | 3
where Sess.artid is a foregin key to art.id.
From the tables above we can see that there are 3 sessions: A,B,C,D, A,D,E,F and A,B,G,D.
I want to get a ranking of the arts that occur along with art A. Something like:
D=3
B=2
How could I form such a query in mysql or postgres?
You need to join twice the session table to get the article sharing the same session.
Then join one time with article for the filter clause, and another time to get the name of the other article in the other session.
SELECT aSameSession.art, count(*)
FROM art a
INNER JOIN Sess s
ON a.id = s.artid
INNER JOIN Sess sSameArticle
ON sSameArticle.sessid = s.sessid
INNER JOIN art aSameSession
ON sSameArticle.artid = aSameSession.id
WHERE A.art = 'A'
AND aSameSession.art <> 'A'
GROUP BY aSameSession.art
Output :
B 2
C 1
D 3
E 1
F 1
G 1
This version could be a little difficult to understand, so here a version just with the ID of the article, which is much more simple :
SELECT sSameArticle.artid, count(*)
FROM Sess s
INNER JOIN Sess sSameArticle
ON sSameArticle.sessid = s.sessid
WHERE s.artid = 1
AND sSameArticle.artid != 1
GROUP BY sSameArticle.artid
Output :
2 2
3 1
4 3
5 1
6 1
7 1
Adding the name of the article is just cosmetic.
Something like this, perhaps:
select art,count(*)
from sessid
left join art on art.id=artid
where sessid in (select sessid from sess where artid=1)
group by artid;
?
Example of table structure and join queries on PostgreSQL
CREATE TABLE arts (
arts_id serial PRIMARY KEY,
name text NOT NULL
);
CREATE TABLE sessions (
sessions_id integer NOT NULL,
arts_id integer NOT NULL REFERENCES arts
);
SELECT arts.name, count(sessions_id)
FROM arts
JOIN sessions USING (arts_id)
GROUP BY arts.name
ORDER BY count(sessions_id) DESC;
SELECT a.art, count(*) as ranking
FROM art a, sess s
WHERE a.id = s.artid
group by a.art
order by count(*) DESC;
For a statement in ANSI-92 syntax have a look at Konerak's answer.