Looking for query in MS Access for below question-
Following is my data set where last row is with NULL in Value column. Also by doing Max(Value) for each Name+Office+Person+Category, I have extracted this data to avoid multiple rows with value
ID Name Office Person Category Value
1 FMR Americas Ben Global 7
1 FMR London Ben Global 5
1 FMR London Ben Overall 4.2
156 Asset London Ben Global 13
156 Asset London Ben Overall
157 WSR Paris Zen Global 2
My Expected result set is as below- I am expecting cross mark or any indicator which will show that for ID,Name,Office,person combination has value for Global/Overll categories or not in single row. I know it's somewhat of similar to "String aggregation"
ID Name Office Person Global Overall
1 FMR Americas Ben X
1 FMR London Ben X X
156 Asset London Ben X
157 WSR Paris Zen X
Appreciate your inputs..
I played around with this a little. I created two select queries Global and Overall
Global
SELECT ID, Name, Office, Person, Category AS Global
FROM [YourTable]
WHERE Category="Global" AND Value IS NOT NULL
Overall
SELECT ID, Name, Office, Person, Category AS Overall
FROM [YourTable]
WHERE Category="Overall" AND Value IS NOT NULL
Then I created a new query to join the select queries
SELECT g.ID, g.Name, g.Office, g.Person, Global, Overall
FROM Global g
LEFT JOIN Overall o ON g.ID = o.ID AND g.Name = o.Name AND g.Office = o.Office AND g.Person = o.Person
Hope this helps.
First, get a list of unique id/name/office combinations:
SELECT DISTINCT ID, Name, Office, Person
FROM TableName
Next, create subqueries for each category:
For Global:
SELECT ID, Name, Office, Person
FROM TableName
WHERE Category="Global"
For Overall:
SELECT ID, Name, Office, Person
FROM TableName
WHERE Category="Overall"
Finally, left join the subqueries to the main query, and use an expression to show the X:
SELECT DISTINCT ID, Name, Office, Person
Iif(Global.ID Is Not Null, "X") AS IsGlobal,
Iif(Overall.ID Is Not Null, "X") AS IsOverall
FROM (TableName
LEFT JOIN (
SELECT ID, Name, Office, Person
FROM TableName
WHERE Category="Global"
) AS Global
ON TableName.ID=Global.ID
AND TableName.Name=Global.Name
AND TableName.Office=Global.Office
AND TableName.Person=Global.Person)
LEFT JOIN (
SELECT ID, Name, Office, Person
FROM TableName
WHERE Category="Overall"
) AS Overall
ON TableName.ID=Overall.ID
AND TableName.Name=Overall.Name
AND TableName.Office=Overall.Office
AND TableName.Person=Overall.Person
It may be easier for you to save the subqueries as Access queries and reference the saved queries by name, instead of including the whole subquery in this query.
Related
I'm trying to run a query that returns distinct AddressIDs.
The row to be retuned for each AddressID should be the one with the latest ReadDate.
I also want to return the value from (non-aggregate) columns PhoneNumber, SomeCode, and Country for the given records.
There are similar questions on here to mine, but nothing seems to suit my exact situation. I've tried different subqueries and making the other columns aggregates, but I can't seem to get the results I desire.
Say the base of the query like:
select cr.AddressID, cr.ReadDate, in.PhoneNumber, in.SomeCode, in.Country
from CustomerReadings cr, in.CustomerInfo
where cr.AddressID = in.AddressID
For example, if I have a table that looks like:
AddressID ReadDate PhoneNumber SomeCode Country
1005 01/01/1997 5556565 GHS Canada
1005 05/06/2006 5556753 ROT USA
1005 08/12/2018 5552345 JKR USA
2007 02/05/2012 5558746 MSC Canada
2007 12/07/2018 5552345 RRE France
4000 03/01/1999 5552345 RRE France
4000 09/05/2007 5551243 MSR USA
I want the query results to look like:
AddressID ReadDate PhoneNumber SomeCode Country
1005 08/12/2018 5552345 JKR USA
2007 12/07/2018 5552345 RRE France
4000 09/05/2007 5551243 MSR USA
If anything is unclear please let me know and I'll update my question accordingly.
In the case of 1 table as you used in your answer example, the code works.
But when I bring in another table, I no longer get just one distinct AddressID back, eg:
select (or select distinct)
cr.AddressID, cr.ReadDate, in.PhoneNumber, in.SomeCode, in.Country
from
CustomerReadings cr,
CustomerInfo in
where
cr.AddressID = in.AddressID
and cr.ReadDate =
(select max(cr2.ReadDate)
from CustomerReadings cr2
where cr2.AddressID = cr.AddressID)
order by
2 desc,
1;
There should be questions that are very similar. I use a correlated subquery:
select t.*
from t
where t.readdate = (select max(t2.readdate) from t t2 where t2.addressid = t.addressid);
You need correlated subquery :
select t.*
from table t
where readdate = (select max(t1.readdate) from table t1 where t1.addressid = t.addressid);
If you are working with latest version of MySQL, then row_number() would helpful :
select t.*
from (select t.*,
row_number() over (partition by addressid order by readdate desc) as seq
from table t
) t
where seq = 1;
However, if the readdate has ties, then row_number() would no longer help use dense_rank() instead.
I want to return an associative array based on a mySQL query such that the query results in 3 columns which are a count of a single set of data in 3 different ways. My best solution is a bit unweildly and I'm hoping there's a better way as there are some irrelevant complexities not shown below. Specifically I have a user table with a user number, their gender, and a place - the place being the dynamic variable which needs to be bound into the query later (in this instance I'm looking for place = 1). The basic table looks like this:
user gender place
1 m 1
2 m 2
3 f 1
4 m 1
5 f 2
I'd like to return 3 columns which are total, total male, total female at place 1.
My first attempt returns 3 rows with the right values, but as they are rows I can't access them cleanly using an associative array:
SELECT COUNT(DISTINCT user) as total FROM users WHERE place=1
UNION ALL
SELECT COUNT(DISTINCT id_customer) as male FROM users
WHERE gender = 'm' AND place=1
UNION ALL
SELECT COUNT(DISTINCT id_customer) as female FROM users
WHERE gender = 'f' AND place=1
My second attempt gives me the correct result but seems a bit verbose as I'll have to bind the place variable 3 times - is there a better way to do this?
SELECT total, male, female FROM
(SELECT COUNT(DISTINCT user) as total FROM users
WHERE place=1
) as total
INNER JOIN
(SELECT COUNT(DISTINCT user) as male FROM users
WHERE place=1 AND gender='m') as male
INNER JOIN
(SELECT COUNT(DISTINCT user) as female FROM users
WHERE place=1 AND gender='f') as female
Do you need the DISTINCT part? or is "user" field unique (primary key or otherwise)?
I prepared both versions in http://sqlfiddle.com/#!9/928fa/7
If user is unique, then this should be enough:
SELECT count(1), sum(gender='m'), sum(gender='f')
FROM users
WHERE place=1;
I have no idea how to finish this query....
The question asks:
"For each person who acted in a movie in 2010, find their name
and total pay in all movies in which they have acted (i.e. including
those not in 2010)."
The table required: (where title = Movie title, and year = Movie year, and Pay = actors pay)
ActedIn (name:varchar, title:varchar, year:int, pay:real)
My query so far:
SELECT A.name, A.pay FROM ActedIn A WHERE A.year = 2010;
This returns:
+--------+--------+
| Name | Pay |
+--------+--------+
| Dino | 12.22 |
+--------+--------+
| Miro | 1238.22|
+--------+--------+
But, this only returns the pay for the money received for the specific movie made by the actor in 2010.
Now that I have the names of the actors I want to look up, I need it to find all the other movies they made (before or after 2010), and add TOTAL PAY for all the movies they were in.
I know I need to make another table to find all the movies those 2 actors acted in, and then merge the columns I think.
Any help?
You can do this with a single aggregation and having clause:
select ai.name, sum(ai.pay)
from actedin ai
group by ai.name
having sum(case when ai.year = 2010 then 1 else 0 end) > 0;
The having clause counts the number of movies that each "name" acted in in 2010. If this number is greater than 0, then the name is kept for the result set.
You can also use exists with a subquery.
select name, sum(pay)
from actedin a
where exists (select 1 from actedin b where a.name = b.name and year = 2010)
group by name
select name, sum(pay)
from actedin
where name in (select name from actedin where year = 2010)
group by name
I can't seem to find a suitable solution for the following (probably an age old) problem so hoping someone can shed some light. I need to return 1 distinct column along with other non distinct columns in mySQL.
I have the following table in mySQL:
id name destination rating country
----------------------------------------------------
1 James Barbados 5 WI
2 Andrew Antigua 6 WI
3 James Barbados 3 WI
4 Declan Trinidad 2 WI
5 Steve Barbados 4 WI
6 Declan Trinidad 3 WI
I would like SQL statement to return the DISTINCT name along with the destination, rating based on country.
id name destination rating country
----------------------------------------------------
1 James Barbados 5 WI
2 Andrew Antigua 6 WI
4 Declan Trinidad 2 WI
5 Steve Barbados 4 WI
As you can see, James and Declan have different ratings, but the same name, so they are returned only once.
The following query returns all rows because the ratings are different. Is there anyway I can return the above result set?
SELECT (distinct name), destination, rating
FROM table
WHERE country = 'WI'
ORDER BY id
Using a subquery, you can get the highest id for each name, then select the rest of the rows based on that:
SELECT * FROM table
WHERE id IN (
SELECT MAX(id) FROM table GROUP BY name
)
If you'd prefer, use MIN(id) to get the first record for each name instead of the last.
It can also be done with an INNER JOIN against the subquery. For this purpose the performance should be similar, and sometimes you need to join on two columns from the subquery.
SELECT
table.*
FROM
table
INNER JOIN (
SELECT MAX(id) AS id FROM table GROUP BY name
) maxid ON table.id = maxid.id
The problem is that distinct works across the entire return set and not just the first field. Otherwise MySQL wouldn't know what record to return. So, you want to have some sort of group function on rating, whether MAX, MIN, GROUP_CONCAT, AVG, or several other functions.
Michael has already posted a good answer, so I'm not going to re-write the query.
I agree with #rcdmk . Using a DEPENDENT subquery can kill performance, GROUP BY seems more suitable provided that you have already INDEXed the country field and only a few rows will reach the server. Rewriting the query giben by #rcdmk , I added the ORDER BY NULL clause to suppress the implicit ordering by GROUP BY, to make it a little faster:
SELECT MIN(id) as id, name, destination as rating, country
FROM table WHERE country = 'WI'
GROUP BY name, destination ORDER BY NULL
You can do a GROUP BY clause:
SELECT MIN(id) AS id, name, destination, AVG(rating) AS rating, country
FROM TABLE_NAME
GROUP BY name, destination, country
This query would perform better in large datasets than the subquery alternatives and it can be easier to read as well.
This is a doubt on mysql select query
let me axplain my doubt with a simple example
consider this is my query
SELECT dbCountry from tableCountry
tableCountry has fields dbCuntryId, dbCountry and dbState
I have the result as
dbCountry
india
america
england
kenya
pakisthan
I need the result as
1 india
2 america
3 england
4 kenya
5 pakisthan
the numbers 12345 must be generated with the increase in data and it is not an autoincrement id.
How can i get it
is it something like loop
You can try this:
SELECT dbCountry,
(SELECT COUNT(*) FROM tableCountry t2 WHERE t2.dbCountry <= t1.dbCountry)
AS RowNum
FROM tableCountry t1
ORDER BY dbCountry
The following should do what you need. It uses a variable that is incremented and returned for each row:
SELECT
#rownum:=#rownum+1 number,
c.dbCountry
FROM
tableCountry c,
(SELECT #rownum:=0) r
If you want the result to always be in the same order you'll need to add an order by constraint to the query, for example, ORDER BY c.dbCountry to order by the country name.