It is kind of challenge. The expected output, all fruits are from ny or ak state and if the mark good=price 10 and bad= price 20 and OK= price 40. So, apple from ny state, have mark good and bad match the price 10 and 20, and apple don't have mark OK row, so no need to compare that. Banana mark bad = price 20, but OK is not equal price 40, so I will rule out banana. pear match OK = price 40 and state=ny and no rows of good and bad mark. Therefore, my output should be apple and pear. How should I do that?
<?php
/*
fruit state price mark
apple ny 10 good
apple ny 20 bad
banana ny 20 bad
banana ny 30 OK
pear ny 40 OK
berry pa 10 good
*/
/*this is my best query but fail to do what I expected*/
SELECT fruit FROM table WHERE state IN ('ny','ak') AND mark IN ('good', 'bad', 'OK') AND price IN ( '10','20','40') GROUP BY fruit
?>
you should where and or condition
You should use a pair of not in
select distinct fruit from my_table
where fruit not in (select distinct fruit from my_table
where (mark, price) not in (select 'good', 10 from dual
union
select 'bad, 20 from dual
union
select 'OK', 40 from dual))
state IN ('ny','ak') ;
The list of potential fruit that could be returned, because a row matches the specification:
SELECT t.fruit
FROM `table` t
WHERE t.state IN ('ny','ak')
AND ( ( t.mark = 'good' AND t.price = 10 )
OR ( t.mark = 'bad' AND t.price = 20 )
OR ( t.mark = 'OK' AND t.price = 40 )
)
GROUP BY t.fruit
A list of fruit that we don't want to return, because there is a row that doesn't satisfy the specification:
SELECT t.fruit
FROM `table` t
WHERE t.state IN ('ny','ak')
AND NOT ( t.mark = 'good' AND t.price = 10 )
AND NOT ( t.mark = 'bad' AND t.price = 20 )
AND NOT ( t.mark = 'OK' AND t.price = 40 )
GROUP BY t.fruit
Note that this will also include rows where the mark column has a value other than good, bad or OK. If we want to ignore rows with other values of mark, then we'd add...
AND t.mark IN ('good','bad','OK')
That gives us two sets. We can combine those with an antijoin operation. As an example of what that looks like, if we had tables fruit_to_include and fruit_to_exclude ...
SELECT i.fruit
FROM fruit_to_include i
LEFT
JOIN fruit_to_exclude e
ON e.fruit = i.fruit
WHERE e.fruit IS NULL
ORDER BY i.fruit
We can replace those placeholder table names with inline views, using the queries that give us the fruit to include and fruit to exclude. The only difference here is replacing the dummy table name with (what MySQL refers to as) derived table.
SELECT i.fruit
FROM -- fruit_to_include
( SELECT t.fruit
FROM `table` t
WHERE t.state IN ('ny','ak')
AND ( ( t.mark = 'good' AND t.price = 10 )
OR ( t.mark = 'bad' AND t.price = 20 )
OR ( t.mark = 'OK' AND t.price = 40 )
)
GROUP BY t.fruit
) i
LEFT
JOIN -- fruit_to_exclude
( SELECT r.fruit
FROM `table` r
WHERE r.state IN ('ny','ak')
AND r.mark IN ('good','bad','OK')
AND NOT ( r.mark = 'good' AND r.price = 10 )
AND NOT ( r.mark = 'bad' AND r.price = 20 )
AND NOT ( r.mark = 'OK' AND r.price = 40 )
GROUP BY r.fruit
) e
ON e.fruit = i.fruit
WHERE e.fruit IS NULL
ORDER BY i.fruit
Related
my table structure is like this
username Period Numberproduced stockonhand totalavailableforsale actualsale Inventoryremaining
pranab 1 100 2000 2100 2000 100
pranab 2 200 100 300 500 0
pranab 3 400 0 400 100 300
pranab 4 500 300 800 400 400
stockinhand of period-1 is always constant=2000.
stockinhand of period-2 is= inventoryremaining of period-1 & so on
can u please tell the query to execute this.
If Period field is unique and increment, then this solution should work:
SELECT
A.*
, [stockinhand] = IIF(A.[Period] = 1, 2000, B.[inventoryremaining])
FROM
[Table] AS A
CROSS APPLY
(SELECT TOP 1 *
FROM
[Table] AS B
WHERE
A.[Period] > B.[Period]
ORDER BY
B.[Period] DESC
) AS B
also note, that if you are using SQL Server 2012 or newer, LAG or LEAD clause will simplify the solution.
If period is sequential (no gaps) use -
select t.*
,coalesce
(
(select Inventoryremaining
from mytable as t2
where t2.period = t.period - 1
)
,2000
) as stockonhand
from mytable t
else use -
select t.*
,coalesce
(
(select Inventoryremaining
from mytable as t2
where t2.period < t.period
order by t2.period
desc limit 1
)
,2000
) as stockonhand
from mytable t
I am trying to connect three table. The output will be like this: Get fruit match price 4 first on table_1 and exclude any fruit with mark 6 on table_2, then at last, on table_3, if the fruit factor match, then get the value of val, if not, I still keep the fruit with val NULL value. I was thinking JOIN, but not so sure how to combine three tables to do what i want. Help, appreciate.
<?php
/*
table_1
fruit price
apple 4
banana 5
pear 4
table_2
fruit mark
apple 5
banana 4
pear 6
table_3
fruit factor val
apple 56 good
banana 89 good
pear 56 bad
*/
$sql = $wpdb->get_results( $wpdb->prepare("
SELECT a.fruit, b.fruit, c.fruit, c.val
FROM table_1 a, table_2 b, table_3 c WHERE a.price = %d AND b.fruit NOT IN
( SELECT fruit FROM table_2 WHERE mark =%d ) AND c.fruit = a.fruit OR c.factor = %d
",$price,$mark,%factor));
foreach($sql as $sqls){
$result1 = $sqls-> a.fruit;
$result2 = $sqls-> c.val;
$result[] = array($result1=>$result2);
}
?>
SELECT
a.fruit,b.mark,c.factor,c.value
from table_1 a,
left join table_2 b
on b.fruit=a.fruit and b.mark != 6
left join table_3 c
on c.fruit=a.fruit
I'm trying to make this query work:
SELECT
IFNULL(SUM(days), 0) AS days
FROM
`table_days`
WHERE task = 1
GROUP BY task
UNION
ALL
SELECT
IFNULL(SUM(total), 0) AS total
FROM
`table_total`
WHERE task = 1
GROUP BY task ;
I have two tables :
1. table_days
id task days
==========================
1 1 3.00
2 1 2.00
2. table_total
id task total
==========================
1 3 0.00
The query above partially works, the result is:
stdClass Object
(
[days] => 5.00
)
but I would like to get the result from second table even if there are no records found. Something like
stdClass Object
(
[days] => 5.00
[total] => 0.00
)
Try This query
SELECT
IFNULL(SUM(days), 0) AS days
FROM
`table_days`
WHERE task = 1
GROUP BY task
UNION
ALL
SELECT
SUM(case when task = 1 then IFNULL(total,0) else 0 end) AS total
FROM
`table_total`
GROUP BY task ;
This code will work for you (example at sqlfiddle):
SELECT
IFNULL(SUM(days), 0) AS value, 'days' as name
FROM
`table_days`
WHERE task = 1
GROUP BY task
UNION ALL
(SELECT CASE WHEN u.value = -1 then 0 else value end as value, 'total' as name
FROM
(
SELECT
IFNULL(SUM(total), 0) AS value
FROM
`table_total`
WHERE task = 1
GROUP BY task
UNION
SELECT -1 as value
) u
);
And it will return:
+-------+-------+
| value | name |
+-------+-------+
| 5 | days |
| 0 | total |
+-------+-------+
The conundrum with your current approach is that the second half of your UNION query doesn't "know" anything about the tasks which appear in the first half.
However, joining the two tables would allow you to leverage the relationship between the two tables. I think a better way of doing this would be to LEFT JOIN the table_days table with table_total, thereby retaining all tasks:
SELECT t1.task, t1.sum_days, t2.sum_total
FROM
(
SELECT task, IFNULL(SUM(days), 0) AS sum_days
FROM `table_days`
GROUP BY task
) t1
LEFT JOIN
(
SELECT task, IFNULL(SUM(total), 0) AS sum_total
FROM `table_total`
GROUP BY task
) t2
ON t1.task = t2.task
WHERE t1.task = 1
If you want to include all tasks from the table_days table, you can remove the WHERE clause.
I'll try to explain the problem as good as possible.
I have two tables "users1213" which is a table of players and "Loanperiodes". Now I'm trying to get immediately with a sql-query a list of players who is at the moment at the club. If they are on loan to another club they don't have to be on the list. It's also possible that the club is loaning a player so these players have to be on the list as well. So I have this for the moment (the club has an id "1" and the team has also an id "1"):
SELECT users1213.id, surname, name, team, club, loanclub
FROM users1213
LEFT JOIN loanperiode ON users1213.id = loanperiode.player
WHERE users1213.status = 'player'
AND (
(
users1213.club != '1'
AND loanperiode.loanclub = '1'
AND loanperiode.begin <= '2013-02-03'
AND loanperiode.end >= '2013-02-03'
AND (
uitleenperiodes.team_id = '1'
)
)
OR (
users1213.club = '1'
AND users1213.team = '1'
AND (
loanperiode.loanclub IS NULL
OR (
loanperiode.loanclub IS NOT NULL
AND (
loanperiode.begin < '2013-02-03'
AND loanperiode.end < '2013-02-03'
)
OR (
uitleenperiodes.begin > '2013-02-03'
AND uitleenperiodes.end > '2013-02-03'
)
)
)
)
)
GROUP BY users1213.id
ORDER BY name
LIMIT 0 , 30
With this query I get a good result but there is 1 problem, when someone had got 2 loanperiodes. For example PLAYER1 is loaned now to CLUB A so he may not be listed. But when PLAYER1 has also got a loanperiode which has already expired, to CLUB B, PLAYER1 will be listed because of the LEFT JOIN. Is there a solution to solve this with a query or must I check afterwards when I'm running the array?
Many thanks!
SELECT users1213.id, surname, name, team, club, loanclub
FROM users1213
LEFT JOIN loanperiode ON users1213.id = loanperiode.player
AND '2013-02-03' BETWEEN loanperiode.begin AND loanperiode.end
WHERE
loanperiode.loanclub = '1'
OR (loanperiode.loanclub IS NULL -- I suppose this happens only when there is no loan between those dates so nothing LEFT JOINed
AND users1213.club = '1')
ORDER BY name
This example supposes that user can have only one loan at once (yes, he can have more loans ended in history, but only one begins before today and ends in the future).
I have this table:
This selection is is duplicated many times for different var_lines (which pretty much work as one row of data, or respondent for a survey) and set_codes (different survey codes).
With this query:
SELECT
*, COUNT(*) AS total
FROM
`data`
WHERE
`var_name` = 'GND.NEWS.INT'
AND(
`set_code` = 'BAN11A-GND'
OR `set_code` = 'BAN09A-GND'
OR `set_code` = 'ALG11A-GND'
)
AND `country_id` = '5'
GROUP BY
`data_content`,
`set_code`
ORDER BY
`set_code`,
`data_content`
The query basically counts the number of answers for a specific question. Then groups them survey (set_code).
What I need is for each of the grouped data_content answers for GND.NEWS.INT to also show the SUM of all the corresponding GND_WT with the same var_line.
For example if I had this:
data_id data_content var_name var_line
1 2 GND.NEW.INT 1
2 1.4 GND_WT 1
3 2 GND.NEW.INT 2
4 1.6 GND_WT 2
5 3 GND.NEW.INT 3
6 0.6 GND_WT 3
I would get something like this:
data_id data_content var_name var_line total weight
1 2 GND.NEW.INT 1 2 3
5 3 GND.NEW.INT 3 1 0.6
Thanks for any help.
Your requirements are not exactly clear, but I think the following gives you what you want:
select d1.data_id,
d1.data_content,
d1.var_name,
d1.var_line,
t.total,
w.weight
from data d1
inner join
(
select data_content,
count(data_content) Total
from data
group by data_content
) t
on d1.data_content = t.data_content
inner join
(
select var_line,
sum(case when var_name = 'GND_WT' then data_content end) weight
from data
group by var_line
) w
on d1.var_line = w.var_line
where d1.var_name = 'GND.NEW.INT'
See SQL Fiddle with Demo
This Query can be suitable for your specific example:
select st.data_id,
st.data_content,
st.var_name,
st.var_line,
count(st.data_id) as total,
sum(st1.data_content) as weight
from data st
left join data st1 on st1.var_name = 'GND_WT' AND st1.var_line=st.var_line
where st.var_name='GND.NEW.INT'
group by st.data_content
Regards,
Luis.