Assuming I have 2 tables:
leave_type
id name
1 maternity leave
2 Medical leave
3 Casual Leave
4 Sick Leave
5 honeymoon Leave
employee_leave_blance
id employee_id year leave_type_id val
1 4 2015 1 9
2 4 2015 2 5
3 8 2015 1 10
4 4 2015 3 4
Here employee_leave_blance.leave_type_id = leave_type.id
Now I want to get all Leave Type values for employee_id=4
In employee_leave_blance table for employee_id=4 there are only 3 leave_type entries but in leave_type table there are 5 of them.
I want to get 5 entries for a employee. If no entry is found in employee_leave_blance it should return 0.
Let me give an example: I want to get output for employee_id = 4
employee_id name val
4 maternity leave 9
4 Medical leave 5
4 Casual Leave 4
4 Sick Leave 0
4 honeymoon Leave 0
For this I've tried following query:
select
el.employee_id, lt.name, el.val from leave_type as lt
left join employee_leave_blance as el on el.leave_type_id = lt.id
where
el.year = YEAR(CURDATE()) and el.employee_id = 4
It however returns following results:
employee_id name val
4 maternity leave 9
4 Medical leave 5
4 Casual Leave 4
Now how can I get values for all leave_type for an employee?
Not sure if this is what you need, please try :
select ifnull(el.employee_id,4) as employee_id,
lt.name,ifnull(el.val,0) as val
from leave_type as lt
left join (select year,employee_id,val,leave_type_id
from employee_leave_balance) as el
on el.leave_type_id = lt.id
and el.year = year(curdate())
and el.employee_id = 4
Actually, your query would works with some modification. just remove where clause to and because you already joined tables and use ifnull function to return 0 for null values. This is your query with some improvement :
select
ifnull(el.employee_id,4) as employee_id, lt.name, ifnull(el.val,0) as val
from leave_type as lt
left join employee_leave_balance as el on el.leave_type_id = lt.id
and
el.year = YEAR(CURDATE()) and el.employee_id = 4
Related
How can I query the data where id_konsul = 4, and how can I get the latest staflow from created_at if it is the same?
example
id id_konsul staflow created_at
1 4 1 21/05/2018 11.03
2 4 2 22/05/2018 11.03
3 4 3 23/05/2018 11.03
4 4 4 24/05/2018 11.03
5 4 5 25/05/2018 11.03
6 4 6 26/05/2018 11.03
7 4 7 27/05/2018 11.03
8 4 6 28/05/2018 11.03
9 4 7 29/05/2018 11.03
10 4 7 30/05/2018 11.03
11 4 8 31/05/2018 11.03
than i get this
id id_konsul staflow created_at
1 4 1 21/05/2018 11.03
2 4 2 22/05/2018 11.03
3 4 3 23/05/2018 11.03
4 4 4 24/05/2018 11.03
5 4 5 25/05/2018 11.03
8 4 6 28/05/2018 11.03
10 4 7 30/05/2018 11.03
11 4 8 31/05/2018 11.03
try this query
SELECT * FROM test1 n
WHERE created_at=(SELECT MAX(created_at)FROM test1
WHERE staflow=n.staflow)
order by id
To get latest row per staflow attribute you can use a self join
select a.*
from demo a
join (
select id_konsul,staflow, max(created_at) created_at
from demo
where id_konsul = 4
group by id_konsul, staflow
) b on a.staflow = b.staflow
and a.id_konsul = b.id_konsul
and a.created_at = b.created_at;
Or using a left join
select a.*
from demo a
left join demo b on a.id_konsul = b.id_konsul
and a.staflow = b.staflow
and a.created_at < b.created_at
where a.id_konsul = 4
and b.id_konsul is null
Demo
To write above queries using laravel's query builder you can use following references
Laravel Eloquent select all rows with max created_at
Laravel - Get the last entry of each UID type
Laravel Eloquent group by most recent record
Please try this query.
SELECT * FROM table_name WHERE id_konsul = 4 ORDER BY created_at DESC LIMIT 1;
You can user INNER JOIN.
Example:
SELECT t0.* from {TABLE_NAME} AS t0 INNER JOIN {TABLE_NAME} t1 ON t0.staflow = t1.staflow WHERE t0.created_at > t1.created_at and t0.id_konsul = 4
I'm working with PHP and MySql. I'm trying to find a way to select a number of movies from a mysql table, but apart from the movies table I have a watchlist table that stores a userID and the movieID of the movies he/she has added to his/her watchlist:
id userID movieID
=====================================
1 1 3
2 1 5
3 1 7
4 2 3
5 2 2
6 3 2
The movies table looks something like this
movieID title duration
=============================
1 tit1 34:43
2 tit2 35:43
3 tit3 24:43
4 tit4 34:13
5 tit5 11:43
6 tit6 22:43
7 tit7 33:43
The result I'm after is (for example for the user with ID 1):
movieID title duration added
=======================================
1 tit1 34:43 false
2 tit2 35:43 false
3 tit3 24:43 true
4 tit4 34:13 false
5 tit5 11:43 true
6 tit6 22:43 false
7 tit7 33:43 true
Is there a way to join both the movies and the watchlist table to produce the desired result?
Thanks.
You can get the required output by using a LEFT JOIN and then checking for a NULL in the join table.
SELECT m.*, IF(w.id IS NULL, 0, 1) AS added
FROM movies m
LEFT JOIN watchlist w ON (m.movieID = w.movieID AND w.userID = 1)
GROUP BY m.movieID
I have four tables look like below:
test_case (1='pass',2='fail',3='skip')
id testing_status
1 1
2 3
3 1
4 2
5 3
6 2
7 2
8 3
test_suite_with_case (referenced with test_case_id in test_case table and test_suite_id with test_suite table)
id test_suite_id test_case_id
1 4 1,3,5,2,6,7,8
2 3 2,5,4,6,7
test_suite
id test_suite_name
3 test_1
4 test_2
test_suite_run (referenced with test_suite_id in test_suite table)
id test_suite_id name
1 3 BBH
2 4 CXN
Now i want to run a where query from test_suite_run by id (for example id=2 in test_suite_run) and want a output look like below:
id(test_suite_run) name test_suite_name pass fail skip
1 CXN test_suite_2 2 2 3
I am new in PHP and MySQL.
Try this:
select
tr.id,
tr.name,
ts.test_suite_name,
sum(testing_status = 1) pass,
sum(testing_status = 2) fail,
sum(testing_status = 3) skip
from test_suite_run tr
inner join test_suite ts on tr.test_suite_id = ts.id
inner join test_suite_with_case tsc on ts.id = tsc.test_suite_id
inner join test_case tc on find_in_set(tc.id, tsc.test_case_id) > 0
group by
tr.id,
tr.name,
ts.test_suite_name;
I'm trying to get a set of values from a pivot table where column A is equal to an array of values, so for example ID 12 has attribute_value_id equal to 3 and 9. Can this be done? I've got this far...
ID | post_id | attribute_id | attribute_value_id
8 12 1 3
9 12 2 13
10 13 1 3
11 13 2 9
12 16 1 3
13 16 2 9
88 11 1 1
89 11 2 8
90 11 3 18
91 11 4 22
The query...
select *
from `searching_for_posts`
where (
select count(*)
from `attributes`
inner join `searching_for_attributes`
on `attributes`.`id` = `searching_for_attributes`.`attribute_id`
where `searching_for_attributes`.`searching_for_post_id` = `searching_for_posts`.`id`
and (`attribute_value_id` = 3 and `attribute_value_id` = 9)
) >= 1
If I use the and then I get no values. If I use the or then I get 3 values but it should return 2. I have limited SQL experience.
You can do this using group by and having. Your logic is hard to follow, but it is something like this:
select post_id
from table t
where attribute_value_id in (3, 9)
group by post_id
having count(distinct attribute_id) = 2;
I would think you would want to check on attribute_id as well, but that doesn't seem to be part of the question.
EDIT:
If these are stored in another table:
select a.post_id
from attributes a join
searching_for_attributes sfa
on a.attribute_id = sfa.attribute_id and
a.attribute_value_id = sfa.attribute_value_id
group by a.post_id
having count(*) = (select count(*) from searching_for_attributes);
In response to #GordonLinoff answer, I've managed to use GROUP BY and HAVING COUNT to get the desired data. Here's what I came up with and hope this helps someone else...
select *
from `searching_for_posts`
where (
select count(*)
from `attributes`
inner join `searching_for_attributes` on `attributes`.`id` = `searching_for_attributes`.`attribute_id`
where `searching_for_attributes`.`searching_for_post_id` = `searching_for_posts`.`id`
and `attribute_value_id` in (3, 9)
having count(distinct `attributes`.`id`) = 2
) >= 1
group by `id`
I need to know if there is a possible way doing this with out subquery..
Here is my table structure:
id-name-father_id
1 joe 0
2 mark 0
3 muller 0
4 miki 2
5 timi 2
6 moses 2
7 david 1
8 momo 0
9 daniel 0
10 ermi 3
My table logic is
0 means he is not a child of some one
1+ mean that he is son of man in that row.
Note: if some one have a child, he still
will have 0 in father id (it's mean there is not grand-fathers in my table)
My query is :
SELECT id, name, count(id=father_id) as sons
WHERE father_id = 0
What I want to get is a list of non-children (father_id=0) and sum
the childrens it has.
Is there a way to get the results without a subquery?
This should do it (MySQL):
SELECT `parents`.`id`, `parents`.`name`, COUNT(`children`.*) AS sons
FROM `people` AS parents
LEFT JOIN `people` AS children ON `parents`.`id` = `children`.`father_id`
WHERE `parents`.`father_id` = 0
GROUP BY `parents`.`id`
According to Gary we need to add name to GROUP BY in other SQL databases:
SELECT `parents`.`id`, `parents`.`name`, COUNT(`children`.*) AS sons
FROM `people` AS parents
LEFT JOIN `people` AS children ON `parents`.`id` = `children`.`father_id`
WHERE `parents`.`father_id` = 0
GROUP BY `parents`.`id`, `parents`.`name`
We are joing the table with itself here. So we join all parents with their children.
This will lead to a result like that:
parents.id parents.name children.id children.name
1 joe 7 david
2 mark 4 miki
2 mark 5 timi
2 mark 6 moses
3 muller 10 ermi
8 momo - - # left join allows this line
9 daniel - -
But now we have each parent several times. So we are GROUP'ing the whole thing over the parent’s id, which will result in the following:
parents.id parents.name COUNT(children.*)
1 joe 1
2 mark 3
3 muller 1
8 momo 0
9 daniel 0
You should be able to do it without any joins or sub-queries as follows:
select case father_id when 0 then id else father_id end id,
max(case father_id when 0 then name end) name,
sum(sign(father_id)) sons
from table
group by case father_id when 0 then id else father_id