I'am working on attendance project. In that i am storing students who are absent on the particular date in the table 'attendance' with fields -> sno,rollno,subject_code,date. And if all the students are present then i will store subject_code, date and rollno as NULL which means'all students are present'
------|--------|------------|-----------|
sno |rollno |subject_code| date |
1 | 1234 | a110 | 12-12-2012|
2 | 1235 | a110 | 12-12-2012|
3 | 1235 | a111 | 14-12-2012|
iam taking the students details from table 'students' with fields -> rollno,name
|--------|-------|
| rollno | name |
| 1234 | xyz |
| 1235 | abc |
| 1236 | mno |
| 1237 | qrs |
Now I want to list the students attendance such that output should be like this for particular date assume list for the date "12-12-2012"
list of "12-12-2012" for subject a110 list of "14-12-2012" for subject a111
|-------|------|---------| |-------|------|---------|
|rollno | name | status | |rollno | name | status |
| 1234 | xyz | Absent | | 1234 | xyz | Present |
| 1235 | abc | Absent | | 1235 | abc | Absent |
| 1236 | mno | Present | | 1236 | mno | Present |
| 1237 | qrs | Present | | 1237 | qrs | Present |
Please Help me..
Use LEFT JOIN to find out which student doesnt have a row in the attendance table. (those where present)
SELECT s.rollno,
s.name,
CASE WHEN a.rollno IS NULL THEN 'Present'
ELSE 'Absent'
END as status
FROM student s
LEFT JOIN attendance a
ON s.rollno = a.rollno
Related
I have this tables People, Ticket, and Report.
+----------+-------+-----+
| idPeople | Name | Age |
+----------+-------+-----+
| 1 | Name1 | 21 |
| 2 | Name2 | 37 |
| 3 | Name3 | 28 |
+----------+-------+-----+
I would like to replace the ForeingKey idPeople with columns Name and Age from People table.
+----------+------------+------------+----------+
| idTicket | ticketCol2 | ticketCol3 | idPeople |
+----------+------------+------------+----------+
| 5 | True | 01/06/99 | 1 |
| 6 | False | 01/06/99 | 2 |
| 7 | True | 01/06/99 | 4 |
+----------+------------+------------+----------+
In the Report table replace the Foreing Key idTicket with ticketCol2, Name, Age from the previous table Ticket with replaced columns (idPeople by Name, Age).
+----------+----------+------------+------------+
| idReport | idTicket | ReportCol3 | ReportCol4 |
+----------+----------+------------+------------+
| 1 | 5 | 01/06/99 | blabla |
| 2 | 7 | 01/06/99 | asdfdd |
| 2 | 6 | 01/06/99 | fooboo |
+----------+----------+------------+------------+
And I the result should be like this table and must be done in one query.
+----------+------------+------------+------------+------------+------+-----+
| idReport | ticketCol2 | ticketCol3 | ReportCol3 | ReportCol4 | Name | Age |
+----------+------------+------------+------------+------------+------+-----+
| 1 | 01/06/99 | abcd | blabla | 123456 | Name | 20 |
| 2 | 01/06/99 | bcda | asdfdd | 321456 | Name | 23 |
| 3 | 01/06/99 | asdf | fooboo | 123456 | Name | 28 |
+----------+------------+------------+------------+------------+------+-----+
I Have tried replacing the foreingkeys with LEFT JOIN and bringing some columns Name and Age to the Ticket table but now the last part where I should replace idTicket with Columns from Ticket is not working.
I have read about the nested JOINs but I cannot understand it very well, I would really appreciate some idea of how I can do it or what should I investigate. Are nested Joins the right way?
The query that I've tried to accomplish the Table Ticket.
SELECT Ticket.ticketCol2, Ticket.ticketCol3, p.Name 'Name', p.Age 'Age'
from Ticket
left join people p on (Ticket.idPeople=p.idPeople);
Try something like this:
SELECT Report.idReport,
Ticket.ticketCol2,
Ticket.ticketCol3,
Report.ReportCol3,
Report.ReportCol4,
People.Name,
People.Age
FROM People
LEFT JOIN Ticket ON Ticket.idPeople = People.idPeople
LEFT JOIN Report ON Report.idTicket = Ticket.idTicket
Like #RiggsFolly said, the Ticket.idPeople won´t match to the People.idPeople, so this will not match any rows.
I have the following table.
table cards
------------------------------------
| card_no | approval_code |
------------------------------------
| 999999xxxxxx1234 | 111111 |
----------------------------------
| 888888xxxxxx5678 | 222222 |
------------------------------------
| 777777xxxxxx9012 | 333333 |
-----------------------------------
| 666666xxxxxx3456 | 444444 |
-----------------------------------
table transactions
---------------------------------------------
| trans_id | pan | approval code | amount |
---------------------------------------------
| A1 | 9012 | 333333 | 9.9|
----------------------------------------------
| A2 | 9012 | 333333 | 10.0|
----------------------------------------------
| B1 | 1233 | 111111 | 11.0|
----------------------------------------------
| B2 | 1234 | 111111 | 12.0|
----------------------------------------------
| C1 | 5678 | 222222 | 13.0|
----------------------------------------------
| C2 | 5678 | 444444 | 13.0|
----------------------------------------------
My output is to display 3 types of output.
1st output is to display matched data and 2nd output is to display unmatched data from cards table and 3rd output is to display unmatched data from transactions table. the following are my codes. transaction table only store pan (last 4 digit from card_no) therefore i need to substr to get the last 4 digit.
for matched data:
$query = $this->db->select (array(
'c.card_no', 'c.approval_code',
't.trans_id','t.pan','t.approval_code','amount'
),false)
-> join('transactions t','t.approval_code = c.approval_code','inner')
-> join('transactions t','t.pan = substr(c.card_no,12)','inner')
-> get('cards c');
for unmatched data from cards table;
$query = $this->db->select (array(
'c.card_no', 'c.approval_code',
't.trans_id','t.pan','t.approval_code','amount'
),false)
-> join('transactions t','t.approval_code != c.approval_code','inner')
-> join('transactions t','t.pan != substr(c.card_no,12)','inner')
-> where ('t.approval_code' IS NULL,NULL,FALSE)
-> where ('t.pan' IS NULL,NULL,FALSE)
-> get('cards c');
for unmatched data from transactions table;
$query = $this->db->select (array(
'c.card_no', 'c.approval_code',
't.trans_id','t.pan','t.approval_code','amount'
),false)
-> join('cards c','t.approval_code = c.approval_code','inner')
-> join('cards c','t.pan != substr(c.card_no,12)','inner')
-> where ('c.approval_code' IS NULL,NULL,FALSE)
-> where ('c.card_no' IS NULL,NULL,FALSE)
-> get('cards c');
Both seems not working.. hmmmm
my expected outputs are:
output matched data
--------------------------------------------------------
| card_no | approval_code | trans_id | amount |
--------------------------------------------------------
| 999999xxxxxx1234 | 111111 | B2 | 12.0 |
-------------------------------------------------------
| 888888xxxxxx5678 | 222222 | C1 | 13.0 |
--------------------------------------------------------
| 777777xxxxxx9012 | 333333 | A1 | 9.9 |
-------------------------------------------------------
| 777777xxxxxx9012 | 333333 | A2 | 10.0 |
-------------------------------------------------------
output unmatched data from table cards
------------------------------------
| card_no | approval_code |
------------------------------------
| 666666xxxxxx3456 | 444444 |
-----------------------------------
output unmatched data from table transactions
---------------------------------------------
| trans_id | pan | approval code | amount |
---------------------------------------------
| B1 | 1233 | 111111 | 11.0|
----------------------------------------------
| C2 | 5678 | 444444 | 13.0|
----------------------------------------------
To get unmatched data from cards table replace join by right join. And for unmatched data from transactions table replace join by left join in respective queries.
For this question I have created a simple example that illustrates what I am asking.
Say I had a table called 'books'
+----+----------------------------+-----------+
| pk | title | author_id |
+----+----------------------------+-----------+
| 1 | The Lost Symbol | 1 |
| 2 | Follow Us Home | 2 |
| 3 | The Man in the High Castle | 3 |
+----+----------------------------+-----------+
(table a)
And another table called 'shops', that had a list of shops that sold each book:
+----+---------+-------------+-------+
| pk | book_id | shop_name | price |
+----+---------+-------------+-------+
| 1 | 1 | WHSmith | 5.00 |
| 2 | 1 | Waterstones | 7.00 |
| 3 | 1 | Amazon | 2.50 |
| 4 | 2 | WHSmith | 4.00 |
| 5 | 2 | Borders | 4.50 |
+----+---------+-------------+-------+
(table b)
If I do a simple select that grabs a book and all of the places it is sold using a join such as:
SELECT
books.*,
shops.shop_name,
shops.price
FROM
books
JOIN shops ON books.pk = shops.book_id
WHERE
book.book_name = "The Lost Symbol"
I would get results such as below:
+----+-----------------+-----------+-------------+-------+
| pk | title | author_id | shop_name | price |
+----+-----------------+-----------+-------------+-------+
| 1 | The Lost Symbol | 1 | WHSmith | 5.00 |
| 1 | The Lost Symbol | 1 | Waterstones | 7.00 |
| 1 | The Lost Symbol | 1 | Amazon | 2.50 |
+----+-----------------+-----------+-------------+-------+
(table c)
However, I would LIKE to receive results like this:
+----+-----------------+-----------+-------------+-------+
| pk | title | author_id | shop_name | price |
+----+-----------------+-----------+-------------+-------+
| 1 | The Lost Symbol | 1 | NULL | NULL |
| 1 | The Lost Symbol | 1 | WHSmith | 5.00 |
| 1 | The Lost Symbol | 1 | Waterstones | 7.00 |
| 1 | The Lost Symbol | 1 | Amazon | 2.50 |
+----+-----------------+-----------+-------------+-------+
(table d)
I.e. the first row is just the result of left outer join and the rest of the results are the the inner join.
An even more desired outcome is:
+------+-----------------+-----------+-------------+-------+
| pk | title | author_id | shop_name | price |
+------+-----------------+-----------+-------------+-------+
| 1 | The Lost Symbol | 1 | NULL | NULL |
| NULL | NULL | NULL | WHSmith | 5.00 |
| NULL | NULL | NULL | Waterstones | 7.00 |
| NULL | NULL | NULL | Amazon | 2.50 |
+------+-----------------+-----------+-------------+-------+
(table e)
Having shop_name and price concatenated and grouped in a single row seems not to work as it only does the first result from shops instead of all of them, also in my real world scenario, I have punctuation in the data so have to be careful with the separator.
So how would I get the result of table e?
You can use UNION ALL to build the required result set:
SELECT pk, title, author_id, NULL AS shop_name, NULL AS price
FROM books
WHERE books.title = "The Lost Symbol"
UNION ALL
SELECT NULL AS pk, NULL AS title, NULL AS author_id, shops.shop_name, shops.price
FROM books
JOIN shops ON books.pk = shops.book_id
WHERE books.title = "The Lost Symbol"
The first part of the union operation returns the first row of the result, i.e. the book title. The second part returns the rest of the rows, i.e.the shop names.
Demo here
Good afternoon everyone,
I wonder if I can get help with this example in a database.
I have listings delivered as:
------------------------------------
| Id | name | price |
-------------------------------
| 1 | Hawaii | 20.58 |
| 2 | Hawaii VIP | 45.58 |
| 3 | Aruba | 13.58 |
| 4 | Aruba VIP | 34.58 |
| 5 | Japon | 14.58 |
| 6 | Japon VIP | 34.58 |
| 7 | Alemania | 14.58 |
| 8 | Alemania VIP | 14.58 |
But I need them to be shown as follows:
-----------------------------------------------------
| Id | name | price basic | price vip
-----------------------------------------------------
| 1 | Hawaii | 20.58 | 45.34 |
| 5 | Japon | 14.58 | 34.58 |
etc etc etc
What I need are the two prices of the same country in a different column in the same query.
As I can catch the "VIP" based on this field and put it in a column with its value
It would be better to store IS_VIP as a separate column in the first table instead of adding it to the name, but since it's not a perfect world, you could solve it like this until then. :)
SELECT
t.Id,
t.name,
t.price as "price basic",
v.price as "price VIP"
FROM YourTable t
JOIN YourTable v ON v.name = CONCAT(t.name, ' VIP')
Sql Fiddle Example
I would like to join two tables and select from two columns the first one if it is not null, of the other if the first is null. As an example imagine that we have the following tables:
names companies_to_names
-------------------------------- -----------------------------
|id_name | name | nickname | | id | id_name | id_company |
-------------------------------- -----------------------------
| 1 | NULL | manu | | 1 | 1 | 1 |
| 2 | Joe A. | NULL | | 2 | 2 | 1 |
| 3 | Bob B. | NULL | | 3 | 3 | 1 |
| 4 | NULL | alice | | 4 | 4 | 1 |
| 5 | NULL | other | | 5 | 5 | 2 |
-------------------------------- -----------------------------
And we want to show either the name, or the nickname of the guys who work for the company with id=1. Then, I want the following result:
--------------------
|id_name | username|
--------------------
| 1 | manu |
| 2 | Joe A. |
| 3 | Bob B. |
| 4 | alice |
--------------------
I was thinking in SELECT CASE WHEN, but I don't know how to do it. Something like:
SELECT NAMES.id_name CASE username
WHEN NAMES.name IS NULL THEN NAMES.nickname
WHEN NAMES.name IS NOT NULL THEN NAMES.name
END
FROM NAMES INNER JOIN COMPANIES_TO_NAMES ON NAMES.id_name = COMPANIES_TO_NAMES.id_name;
Am I right?
Here is a query that shows you how to solve your problem:
SELECT N.id_name
,IFNULL(N.name, N.nickname) AS [username]
,CASE
WHEN N.name IS NOT NULL THEN 'name'
ELSE 'nickname'
END AS [username_source]
FROM NAMES N
INNER JOIN companies_to_names C ON C.id_name = N.id_name
AND C.id = 1
Hope this will help you.