Viewing totals (Format below) - mysql

With the code shown below:
SELECT c.idBase, t.Estado FROM argentina.Tickets_2018 t
LEFT JOIN argentina.ContenidoBases c
ON t.ANI = c.ANI
WHERE t.idCampania = 8 AND t.Fecha BETWEEN "2018-04-04" AND "2018-04-15"
The columns and data retrieved is like this:
Base | Estado
----------------
139 | ANSWER
139 | ANSWER
139 | NOANSWER
139 | NOANSWER
139 | ANSWER
What I want is to view info like this (totals):
Base | Estado | Total
----------------
139 | ANSWER | 3
139 | NOANSWER | 2
What I'm doing wrong in my code? (I have a lot of "Base"s (like 139, 45, 2, etc))

SELECT c.idBase, t.Estado, count(*) as total FROM argentina.Tickets_2018 t
LEFT JOIN argentina.ContenidoBases c
ON t.ANI = c.ANI
WHERE t.idCampania = 8 AND t.Fecha BETWEEN "2018-04-04" AND "2018-04-15"
Group by c.idBase, t.Estado
The group by will allow you to do a count which will give you the total :)

Using COUNT() and GROUP BY, this result is possible:
SELECT c.idBase, t.Estado, COUNT(c.idBase) AS `Total`
FROM argentina.Tickets_2018 t
LEFT JOIN argentina.ContenidoBases c ON t.ANI = c.ANI
WHERE t.idCampania = 8 AND t.Fecha BETWEEN "2018-04-04" AND "2018-04-15"
GROUP BY c.idBase, t.Estado
As seeing in your expected output, Base is the alias name for the id column. If so use SELECT id AS Base, and GROUP BY c.id. If not, your actual column name is idBase use the query above.

Related

Find duplicates from same table and constraint them from another table in sql

Oh, my title is not the best one and as English is not my main language maybe someone can fix that instead of downvoting if they've understood the issue here.
Basically i have two tables - tourneyplayers and results. Tourneyplayers is like a side table which gathers together tournament information across multiple tables - results, tournaments, players etc. I want to check duplicates from the results table over column day1_best, from single tournament and return all the tourneyplayers who have duplicates.
Tourneyplayers contain rows:
Tourneyplayers
tp_id | resultid | tourneyid
1 | 2 | 91
2 | 21 | 91
3 | 29 | 91
4 | 1 | 91
5 | 3 | 92
Results contains rows:
Results:
r_id | day1_best
1 | 3
2 | 1
3 | 4
.. | ..
21 | 1
.. | ..
29 | 2
Now tourney with id = 91 has in total 4 results, with id's 1,2,21 and 29. I want to return values which have duplicates, so currently the result would be
Result
tp_id | resultid | day1_best
1 | 2 | 1
2 | 21 | 1
I tried writing something like this:
SELECT *
FROM tourneyplayers
WHERE resultid
IN (
SELECT r1.r_id
FROM results AS r1
INNER JOIN results AS r2 ON ( r1.day1_best = r2.day1_best )
AND (
r1.r_id <> r2.r_id
)
)
AND tourneyid =91
But in addition to values which had the same day1_best it chose two more which did not have the same. How could i improve my SQL or rewrite it?
First you JOIN both tables, so you know how the data looks like.
SELECT *
FROM tourney_players t
JOIN results r
ON t.`resultid` = r.`r_id`;
Then using the same query you GROUP to see what tourneyid, day1_best combination has multiple rows
SELECT `tourneyid`, `day1_best`, count(*) as total
FROM tourney_players t
JOIN results r
ON t.`resultid` = r.`r_id`
GROUP BY `tourneyid`, `day1_best`;
Finally you use the base JOIN and perform a LEFT JOIN to see what rows has a match and show only those rows.
SELECT t.`tp_id`, r.`r_id`, r.`day1_best`
FROM tourney_players t
JOIN results r
ON t.`resultid` = r.`r_id`
LEFT JOIN (SELECT `tourneyid`, `day1_best`, count(*) as total
FROM tourney_players t
JOIN results r
ON t.`resultid` = r.`r_id`
GROUP BY `tourneyid`, `day1_best`
HAVING count(*) > 1) as filter
ON t.`tourneyid` = filter.`tourneyid`
AND r.`day1_best` = filter.`day1_best`
WHERE filter.`tourneyid` IS NOT NULL;
SQL DEMO
OUTPUT
Please try this :
Select tp.tp_id , tp.resultid ,r.day1_best from (Select * from Tourneyplayers
where tourneyid = 91)as tp inner join (select * from Result day1_best in(select
day1_best from result group by day1_best having count(*)>1 ) )as r on tp.resultid
= r.r_id ;

MySQL query to select the max date for the relation table based on criteria at second level

Here is my SQLFIDDLE
Basically I have three tables, A issues, journals and journal details.
I would like to have in a single query the following way of representation.
id | status_id | X |
90001 | 12 | NULL |
90002 | 12 | NULL |
90003 | 12 | 2015-01-06 |
90004 | 12 | 2015-01-09 |
The rule applied is for X is the max 'journals' created date at which the 'fixed_version_id' == 55 exists.
Please help.
Thank You,
I recommend you start by getting the details of all the journals that meet your requirement like this:
SELECT *
FROM journal_details
WHERE property = 'fixed_version_id' AND value = '55';
Then you can use those values to get the created date of the journal rows that meet this requirement:
SELECT j.issue_id, MAX(j.created_on) AS created_on
FROM journals j
JOIN journal_details jd ON jd.journal_id = j.id AND jd.property = 'fixed_version_id' AND jd.value = '55'
GROUP BY j.issue_id;
From these results, you can join in to get all issues. If you use an outer join, you'll get null for any journals that didn't meet the criteria:
SELECT i.id, i.status_id, tmp.created_on
FROM issues i
LEFT JOIN(
SELECT j.issue_id, MAX(j.created_on) AS created_on
FROM journals j
JOIN journal_details jd ON jd.journal_id = j.id AND jd.property = 'fixed_version_id' AND jd.value = '55'
GROUP BY j.issue_id
) tmp ON tmp.issue_id = i.id;
Here is an SQL Fiddle example.

MySQL subquery from same table

I have a database with table xxx_facileforms_forms, xxx_facileforms_records and xxx_facileforms_subrecords.
Column headers for xxx_facileforms_subrecords:
id | record | element | title | neame | type | value
As far as filtering records with element = '101' ..query returns proper records, but when i add subquery to filete aditional element = '4871' from same table - 0 records returned.
SELECT
F.id AS form_id,
R.id AS record_id,
PV.value AS prim_val,
COUNT(PV.value) AS count
FROM
xxx_facileforms_forms AS F
INNER JOIN xxx_facileforms_records AS R ON F.id = R.form
INNER JOIN xxx_facileforms_subrecords AS PV ON R.id = PV.record AND PV.element = '101'
WHERE R.id IN (SELECT record FROM xxx_facileforms_records WHERE record = R.id AND element = '4871')
GROUP BY PV.value
Does this looks right?
Thank You!
EDIT
Thank you for support and ideas! Yes, I left lot of un guessing. Sorry. Some input/output table data might help make it more clear.
_facileforms_form:
id | formname
---+---------
1 | myform
_facileforms_records:
id | form | submitted
----+------+--------------------
163 | 1 | 2014-06-12 14:18:00
164 | 1 | 2014-06-12 14:19:00
165 | 1 | 2014-06-12 14:20:00
_facileforms_subrecords:
id | record | element | title | name|type | value
-----+--------+---------+--------+-------------+--------
5821 | 163 | 101 | ticket | radio group | flight
5822 | 163 | 4871 | status | select list | canceled
5823 | 164 | 101 | ticket | radio group | flight
5824 | 165 | 101 | ticket | radio group | flight
5825 | 165 | 4871 | status | select list | canceled
Successful query result:
form_id | record_id | prim_val | count
1 | 163 | flight | 2
So i have to return value data (& sum those records) from those records where _subrecord element - 4871 is present (in this case 163 and 165).
And again Thank You!
Thank You for support and ideas! Yes i left lot of un guessing.. sorry . So may be some input/output table data might help.
_facileforms_form:
headers -> id | formname
1 | myform
_facileforms_records:
headers -> id | form | submitted
163 | 1 | 2014-06-12 14:18:00
164 | 1 | 2014-06-12 14:19:00
165 | 1 | 2014-06-12 14:20:00
_facileforms_subrecords
headers -> id | record | element | title | name | type | value
5821 | 163 | 101 | ticket | radio group| flight
5822 | 163 | 4871 | status | select list | canceled
5823 | 164 | 101 | ticket | radio group | flight
5824 | 165 | 101 | ticket | radio group | flight
5825 | 165 | 4871 | status | select list | canceled
Succesful Query result:
headers -> form_id | record_id | prim_val | count
1 | 163 | flight | 2
So i have to return value data (& sum those records) from those records where _subrecord element - 4871 is present (in this case 163 and 165).
And again Thank You!
No, it doesn't look quite right. There's a predicate "R.id IN (subquery)" but that subquery itself has a reference to R.id; it's a correlated subquery. Looks like something is doubled up there. (We're assuming here that id is a UNIQUE or PRIMARY key in each table.)
The subquery references an identifier element... the only other reference we see to that identifier is from the _subrecords table (we don't see any reference to that column in _records table... if there's no element column in _records, then that's a reference to the element column in PV, and that predicate in the subquery will never be true at the same time the PV.element='101' predicate is true.
Kudos for qualifying the column references with a table alias, that makes the query (and the EXPLAIN output) much easier to read; the reader doesn't need to go digging around in the table definitions to figure out which table does and doesn't contain which columns. But please take that pattern to the next step, and qualify all column references in the query, including column references in the subqueries.
Since the reference to element isn't qualified, we're left to guess whether the _records table contains a column named element.
If the goal is to return only the rows from R with element='4871', we could just do...
WHERE R.element='4871'
But, given that you've gone to the bother of using a subquery, I suspect that's not really what you want.
It's possible you're trying to return all rows from R for a _form, but only for the _form where there's at least one associated _record with element='4871'. We could get that result returned with either an IN (subquery) or an EXISTS (correlated_ subquery) predicate, or an anti-join pattern. I'd give examples of those query patterns; I could take some guesses at the specification, but I would only be guessing at what you actually want to return.
But I'm guessing that's not really what you want. I suspect that _records doesn't actually contain a column named element.
The query is already restricting the rows returned from PV with those that have element='101'.)
This is a case where some example data and the example output would help explain the actual specification; and that would be a basis for developing the required SQL.
FOLLOWUP
I'm just guessing... maybe what you want is something pretty simple. Maybe you want to return rows that have element value of either '101' or '4913'.
The IN comparison operator is a convenient of way of expressing the OR condition, that a column be equal to a value in a list:
SELECT F.id AS form_id
, R.id AS record_id
, PV.value AS prim_val
, COUNT(PV.value) AS count
FROM xxx_facileforms_forms F
JOIN xxx_facileforms_records R
ON R.form = F.id
JOIN xxx_facileforms_subrecords PV
ON PV.record = R.id
AND PV.element IN ('101','4193')
GROUP BY PV.value
NOTE: This query (like the OP query) is using a non-standard MySQL extension to GROUP BY, which allows non-aggregate expressions (e.g. bare columns) to be returned in the SELECT list.
The values returned for the non-aggregate expressions (in this case, F.id and R.id) will be a values from a row included in the "group". But because there can be multiple rows, and different values on those rows, it's not deterministic which of values will be returned. (Other databases would reject this statement, unless we wrapped those columns in an aggregate function, such as MIN() or MAX().)
FOLLOWUP
I noticed that you added information about the question into an answer... this information would better be added to the question as an EDIT, since it's not an answer to the question. I took the liberty of copying that, and reformatting.
The example makes it much more clear what you are trying to accomplish.
I think the easiest to understand is to use EXISTS predicate, to check whether a row meeting some criteria "exists" or not, and exclude rows where such a row does not exist. This will use a correlated subquery of the _subrecords table, to which check for the existence of a matching row:
SELECT f.id AS form_id
, r.id AS record_id
, pv.value AS prim_val
, COUNT(pv.value) AS count
FROM xxx_facileforms_forms f
JOIN xxx_facileforms_records r
ON r.form = f.id
JOIN xxx_facileforms_subrecords pv
ON pv.record = r.id
AND pv.element = '101'
-- only include rows where there's also a related 4193 subrecord
WHERE EXISTS ( SELECT 1
FROM xxx_facileforms_subrecords sx
WHERE sx.element = '4193'
AND sx.record = r.id
)
--
GROUP BY pv.value
(I'm thinking this is where OP was headed with the idea that a subquery was required.)
Given that there's a GROUP BY in the query, we could actually accomplish an equivalent result with a regular join operation, to a second reference to the _subrecords table.
A join operation is often more efficient than using an EXISTS predicate.
(Note that the existing GROUP BY clause will eliminate any "duplicates" that might otherwise be introduced by a JOIN operation, so this will return an equivalent result.)
SELECT f.id AS form_id
, r.id AS record_id
, pv.value AS prim_val
, COUNT(pv.value) AS count
FROM xxx_facileforms_forms f
JOIN xxx_facileforms_records r
ON r.form = f.id
JOIN xxx_facileforms_subrecords pv
ON pv.record = r.id
AND pv.element = '101'
-- only include rows where there's also a related 4193 subrecord
JOIN xxx_facileforms_subrecords sx
ON sx.record = r.id
AND sx.element = '4193'
--
GROUP BY pv.value

SQL Query that gives smallest DATE per match

I've been trying to solve this without a post, but i can't find a fitting answer...
I have a SALE-Table and an APPOINTMENT-Table.
In both is a coloumn sale_id.
In APPOINTMENT is the column do_by(date) which can have several entries per sale_id.
What I need is the NEXT appointment PER matching sale_id.
Sth. like this:
appointment_id | sale_id | do_by
--------------------------------------
1365 | 160 | 27.05.2014
2546 | 173 | 29.05.2014
5483 | 265 | 01.06.2014
So far my Query only gives me the smallest do_by of ALL...
SELECT a.appointment_id, a.do_by, s.sale_id
FROM [Askus7].[CRM7].[APPOINTMENT] a, [Askus7].[CRM7].[SALE] s
WHERE (s.sale_id = a.sale_id) AND a.do_by =
(
SELECT MIN(a2.do_by)
FROM [Askus7].[CRM7].[APPOINTMENT] a2, [Askus7].[CRM7].[SALE] s2
WHERE s2.sale_id = a2.sale_id
AND s.sale_id = a.sale_id
)
Thx for your help!
Something like that? (untested)
SELECT a.appointment_id, ms.do_by, a.sale_id
(
SELECT a2.sale_id as sale_id, MIN(a2.do_by) as do_by
FROM [Askus7].[CRM7].[APPOINTMENT] a2 JOIN [Askus7].[CRM7].[SALE] s2
ON a2.sale_id=s2.sale_id
GROUP BY a2.sale_id
)ms
JOIN [Askus7].[CRM7].[APPOINTMENT] a
ON a.sale_id = ms.sale_id and a.do_by = ms.do_by;
warning: if you don't have do_by column indexed and your APPOINTMENT table is large, the query might be quite slow.

MySQL: How to limit results to max value of another field?

In this scenario, I am trying to report on the operating_system_version for each distinct computer_id where the report_id for that computer_id is the greatest.
Currently, I am getting the below results:
operating_system_version | computer_id | report_id
10.8 | 1 | 10
10.9 | 1 | 20
10.9 | 2 | 11
10.8 | 2 | 21
The above is returned by this statement:
SELECT operating_systems.operating_system_version,
reports.computer_id,
reports.report_id
FROM operating_systems
INNER JOIN reports
ON operating_systems.report_id = reports.computer_id
Instead, would like return the most recent (highest report_id) operating_system_version for each distinct computer_id, for example:
operating_system_version | computer_id | report_id
10.9 | 1 | 20
10.8 | 2 | 21
I am brand new to SQL .. Appreciate any help.
You would need to add a group by statement and a having statement.
The group by would look like
group by computer_id
The having would look like
having report_id= (select max(report_id) )
SELECT operating_systems.operating_system_version,
reports.computer_id,
reports.report_id
FROM operating_systems INNER JOIN reports ON operating_systems.report_id = reports.computer_id
WHERE NOT EXISTS (SELECT 1
FROM reports r2
WHERE r2.computer_id = reports.computer_id
AND r2.reports_id > reports.reports_id)
A subquery would lead you to desired end result:
SELECT os.operating_system_version,
r2.computer_id,
MAX(r2.report_id)
FROM (
SELECT DISTINCT computer_id
FROM reports
) r
INNER JOIN operating_systems os
ON os.report_id = r.computer_id
INNER JOIN reports r2
ON r2.computer_id = r.computer_id
Need to do a better job looking through other posts. This question is answered in an excellent post at: SQL Select only rows with Max Value on a Column