Changed the question after peeling the outer layers
I am using MySQL 5.1
select s.status, street, m.meterpointid
from meterpoint m inner join account a
on ( m.accountid = a.accountid) inner join
meterservice s
on ( m.meterpointid = s.meterpointid )
where a.citystateid=1 and m.meterpointid=3008 and m.lastupdate is not null
group by status, street ;
The above query returns
1 210 S HWY 3 3008
select s.status, street, m.meterpointid
from meterpoint m inner join account a
on ( m.accountid = a.accountid) inner join
meterservice s
on ( m.meterpointid = s.meterpointid )
where a.citystateid=1 and m.lastupdate is not null
group by status, street ;
but the output from above query which is exactly the same as the previous query without the m.meterpointid=3008 does not contain the 1 210 S HWY 3 3008
Any ideas?
Thanks
Naren
The change on the inner query is changing the count in the outer query, so having count(*) = 1 is no longer true. I find the best way to diagnose these sorts of things is to peel away outer layers and look at the inner queries until I figure out what is going on.
This is not at all surprising. You are using a (mis)feature of MySQL called Hidden Columns. That is, you have columns in the select clause that are not in the group by clause and are not in aggregation functions.
In this case, an arbitrary value is chosen for the value.
To fix this problem, either do:
group by status, street, m.meterpointid
or
select s.status, street, min(m.meterpointid)
These will fix the query so the results are determinate.
Not including the test m.meterpointid=3008 can change the count. If, according to count(*) = 1, the count is not 1 the result is discarded. If the subselect of the second query returns more than one record, then this result will be discarded.
Related
I want to get the total numbers of committed crimes when combining the two tables.
But I want to count the numbers for each crime being committed and also display the values of those that has not being committed as 0, How can i achieve this using mysql?
my code:
SELECT count(offense_id)
AS totalnumber,(
select offense_description
from offense
where offense.offense_id = case_crime.offense_id
)as crimeName
from case_crime
group by offense_id
To get a list of all your offenses and the count of registered crimes, you need to use the LEFT JOIN between the two tables .... something like this SQL:
SELECT a.offense_id, a.offense_description, count(b.crime_caseid) as total
FROM offense a LEFT JOIN case_crime b
ON a.offense_id = b.offense_id
group by a.offense_id;
Here is a SQLFiddle to play around with :)
You are looking for a LEFT OUTER JOIN
Something like
SELECT offense.offense_id
, offense_description
, count(case_crime.case_id) as Total_Number
from offense
LEFT OUTER JOIN case_crime ON offense.offense_id = case_crime.offense_id
group by offense.offense_id
I'll admit, I'm a TSQL guy, so I would handle the COUNT(*) returning null when there are no cases with the specified offense using: ISNULL(COUNT(case_crime),0)
Other SQL variants might use COALESCE( COUNT(case_crime), 0)
Here is a query:
select
e.eid,
e.event_time as contact_created,
cs.name as initial_class,
cn.create_time as lead_date
from bm_sets.event378 e
inner join bm_config.classes cs on cs.id = e.class_id and cs.cid=378 # and cs.name = 'Candidate'
left join bm_sets.conversion378 cn on cn.eid = e.eid and cn.create_time > e.event_time
where e.eid = 283818
group by eid, contact_created, initial_class, lead_date
The results of this query look like this:
eid, contact_created, initial_class, lead_date
283818 2015-03-07 09:43:42 Hot
283818 2015-03-10 22:19:47 Candidate
283818 2015-03-10 22:22:11 Candidate
I need to adjust this query so that only the first record is returned, the one with the min contact_created date. But since I'm using an aggregate function with other fields, I'm grouping by initial_class too so min is the min based on the combined groupings.
Our server seems to struggle whenever I use a subquery. So I tried using another join as a filter, something like:
inner join bm_sets.event378 e1 on e1.eid = e.eid and e1.event_time < e.event_time
But I know before running it that this won't work since the eid (user id) 283818 will still be returned and thus all associated data.
How can I restrict the results to only those records that correspond to the minimum of event_time?
I am using the where condition 283818 (my own user id for debugging) only as a sanity check as I construct this query. The query, when ready, will not have this condition and the results will thus be for many users.
If you need only top 1 then you can call just
select top 1
or you need make a function that returns you minimum created_contact then you just compare it with current created_contact.
I hope that will help you
Thanks
OK I got it. I used a null left join like so (on the back of other SO posts on the topic of groupwise min/max):
added this to selector:
e1.event_time
added this to joins:
left join bm_sets.event378 e1 on e1.eid = e.eid and e1.event_time < e.event_time
added this to where clause:
and e1.event_time is null
There's a lot of Q&A out there for how to make MySQL show results for rows that have 0 records, but they all involve 1-2 tables/fields at most.
I'm trying to achieve the same ends, but across 3 fields, and I just can't seem to get it.
Here's what I've hacked together:
SELECT circuit.circuit_name, county.county_name, result.adr_result, count( result.adr_result ) AS num_results
FROM
(
SELECT cases.case_id, cases.county_id, cases.result_id
FROM cases
WHERE cases.status_id <> "2"
) q1
RIGHT JOIN county ON q1.county_id = county.county_id
RIGHT JOIN circuit ON county.circuit_id = circuit.circuit_id
RIGHT JOIN result ON q1.result_id = result.result_id
GROUP BY adr_result, circuit_name, county_name
ORDER BY circuit_name, county_name, adr_result
What I need to see is a list of ALL circuits in the first column, a list of ALL counties per circuit in the second column, a list of ALL possible adr_result entries for each county (they're the same for every county) in the third column, and then the respective count for the circuit/county/result combination-- even if it is 0. I've tried every combination of left, right and inner join (I know inner is definitely not the solution, but I'm frustrated) and just can't see where I'm going wrong.
Any help would be appreciated!
Here is a start. I can't follow your problem statement completely. For instance, what is the purposes of the cases table? None the less, when you say "ALL" records for each of those tables, I interpret it as a Cartesian product - which is implemented through the derived table in the FROM clause (notice the lack of the JOIN in that clause)
SELECT everthingjoin.circuit_name
, everthingjoin.county_name
, everthingjoin.adr_result
, COUNT(result.adr_result) AS num_results
FROM
(SELECT circuit.circuit_name, county.county_name, result.adr_result,
FROM circuit
JOIN county
JOIN result) AS everthingjoin
LEFT JOIN cases
ON cases.status_id <> "2"
AND cases.county_id = everthingjoin.county_id
LEFT JOIN circuit
ON everthingjoin.circuit_id = circuit.circuit_id
LEFT JOIN result
ON cases.result_id = result.result_id
GROUP BY adr_result, circuit_name, county_name
ORDER BY circuit_name, county_name, adr_result
try this, see if it provides some ideas:
SELECT
circuit.circuit_name
, county.county_name
, result.adr_result
, ISNULL(COUNT(result.*)) AS num_results
, COUNT(DISTINCT result.adr_result) AS num_distinct_results
FROM cases
LEFT JOIN county
ON cases.county_id = county.county_id
LEFT JOIN circuit
ON county.circuit_id = circuit.circuit_id
LEFT JOIN result
ON cases.result_id = result.result_id
WHERE cases.status_id <> "2"
GROUP BY
circuit.circuit_name
, county.county_name
, result.adr_result
ORDER BY
circuit_name, county_name, adr_result
SELECT area_id,
area_name,
(select count(*) from applications
where claims_status=1 and
center_name=c.area_id) as cont
FROM apparea c where cont<>0
I am trying to get fields and relevant count from anothere table, but the above query is not working. The query is involved two different tables(apparea, applications). The above query has error and I am looking for the alternate way to achieve this.
The alias for your column cont is not available in the WHERE clause. You will want to use something similar to this:
SELECT area_id,
area_name,
cont
FROM
(
SELECT area_id,
area_name,
(select count(*)
from applications
where claims_status=1
and center_name=c.area_id) as cont
FROM apparea c
) c
where cont<>0
This can also be written using a LEFT JOIN:
select c.area_id,
c.area_name,
a.cont
from apparea c
left join
(
select count(*) cont,
center_name
from applications
where claims_status=1
group by center_name
) a
on c.area_id = a.center_name
Try this query
SELECT
c.area_id,
c.area_name,
cnt
FROM
apparea c,
(select
center_name,
count(*) AS cnt
from
applications
where
claims_status=1
GROUP BY
center_name
HAVING
count(*) > 0) cont
where
c.area_id = cont.center_name;
Got the count for each center_name and then joined table to get count for each area
Use HAVING rather than where.
As it is problem with aliases.
It is not permissible to refer to a column alias in a WHERE clause, because the column
value might not yet be determined when the WHERE clause is executed.
See Section C.5.5.4, “Problems with Column Aliases”.
http://dev.mysql.com/doc/refman/5.0/en/problems-with-alias.html
From: http://dev.mysql.com/doc/refman/5.0/en/select.html
Got a query running one sum from a different table, which works perfectly (and obtained from this forum as well):
SELECT
R.REP_ID as repid, R.REP_DESBREV as repdesc,
IFNULL(SUM(RD.REPDATA_CANT), 0) as cant
FROM
REPUESTOS R
LEFT JOIN
REP_DATA RD, ON RD.REPDATA_REPID = R.REP_ID
GROUP BY
RD.REPDATA_REPID
Now, the thing is that I'd like to add an extra column that obtains the total inventory (something like
IFNULL(SUM(I.INV_CANT), 0) as inv)
FROM table INVENTARIO I
WHERE I.INV_REPID = R.REP_ID
This value can be obtained by means of a JOIN, in the exact same way we got the first statement that works, but I have not found the way to include BOTH SUMS in just one query.
Any ideas? THANKS!
Try this query example
select
t1.id,
ifnull(sum(t1.my_column),0) as Sum1,
ifnull(other.sum,0) as Sum2
from table as t1
left join (select id , sum(other_table_column) from other_table group by id) as other
on t1.id = other.id
group by t1.id
I just implemented the following statement:
SELECT
R.REP_PARNUM as parnum,
R.REP_ID as repid,
R.REP_DESBREV as repdesc,
IFNULL(SUM(RD.REPDATA_CANT),0) as cant,
IFNULL(SUM(I.INV_CANT),0) as intt
FROM REPUESTOS R
LEFT JOIN REP_DATA RD ON RD.REPDATA_REPID = R.REP_ID
LEFT JOIN INVENTARIO I ON I.INV_REPID = R.REP_ID
GROUP BY R.REP_PARNUM
It actually runs, but the problem is that it's giving me some weird values. For example, some of the values in the first sum column (REPDATA_CANT) are shown with -3, i.e. if the real result is 20, it shows 17 and so on. In the second sum column (INV_CANT), it actually MULTIPLIES (in some rows, not all) the value by 3. Very weird behaviour, do you have an idea why?