MS access Certain Column into Rows - ms-access

I have below Source Columns, I like to convert into target format shown in MS Access, how do I do that ?
Source Data
Role OrgName Market1 Value1 Market2 Value2 Market3 Value4 Market5 Value5
R1 O1 M1 V1 M2 V2 M3 V3 M4 V4
Target data After Converted.
Role OrgName Market Value
R1 O1 M1 V1
R1 O1 M2 V2
R1 O1 M3 V3
R1 O1 M4 V4

This can be done with a UNION query. There is no wizard or designer for UNION, must type or copy/paste in SQLView of query builder. Limit of 50 SELECT lines. UNION will not allow duplicate rows, use UNION ALL if you want to allow duplicate rows.
SELECT Role, OrgName, Market1 AS Market, Value1 AS Data FROM table
UNION SELECT Role, OrgName, Market2, Value2 FROM table
UNION SELECT Role, OrgName, Market3, Value3 FROM table
UNION SELECT Role, OrgName, Market4, Value4 FROM table;

Related

How to give " Only in " condition in SQL?

I have a table that has columns Name, Series and Season.
Name
series
season
abc
alpha
s1
abc
alpha
s2
pqr
alpha
s1
xyz
beta
s2
xyz
gamma
s3
abc
theta
s1
I am trying to extract the number of people who have watched only the series 'alpha', and not any other series.
How to get this count?
On giving the "where series='alpha' " condition, I get the counts of people who watched alpha, but not the counts of those who watched only alpha eg: abc has watched alpha as well as theta, but pqr has watched only alpha.
You could use a subquery to get only the names which have watched only distinct series and then filter in the where condition your specific serie
select count(yt.name) as only_alpha
from yourtable yt
inner join ( select name
from yourtable
group by name
having count(distinct series) = 1
) yt1 on yt.name=yt1.name
where yt.series='alpha';
https://dbfiddle.uk/n0PavP4H
You can use subquery, like this:
SELECT COUNT(DISTINCT name)
FROM t
WHERE name NOT IN (
SELECT DISTINCT name
FROM t
WHERE series<>'alpha'
) AND series='alpha'
If you really want to get the number of such people only, without their name or any further information, you can use a NOT EXISTS clause like this:
SELECT COUNT(*) AS desiredColumnName
FROM yourtable y
WHERE series = 'alpha'
AND NOT EXISTS
(SELECT 1 FROM yourtable y1 WHERE y.name = y1.name AND series <> 'alpha');
Thus, you can set your condition the person must not appear in any other series but the 'alpha' one.
If the same name can occur in different seasons, you can add a DISTINCT to count them only once. This should only be done if really required because it can slow down the query:
SELECT COUNT(DISTINCT name) AS desiredColumnName
FROM yourtable y
WHERE series = 'alpha'
AND NOT EXISTS
(SELECT 1 FROM yourtable y1 WHERE y.name = y1.name AND series <> 'alpha');
If your description is incorrect and you need also other information, you might do better with a GROUP BY clause etc.
Try out here: db<>fiddle
You can use like below
select sum(Record) as Count from (select count() as Record from yourtable where series='alpha'
group by series,name having count()=1) as data
Check below link
https://dbfiddle.uk/1Y3WZT23
I added some new cases to your table to see other anomalies that can happen. This is how it looks like now:
Name
series
season
abc
alpha
s1
abc
alpha
s2
abc
theta
s1
fgh
alpha
s1
fgh
alpha
s2
klj
gamma
s1
klj
gamma
s2
klj
gamma
s3
pqr
alpha
s1
xyz
beta
s2
xyz
gamma
s3
I maybe overcomplicated, but it can provide the correct result for your problem; you just need to COUNT() it. I tested other SQL queries under your question on my this table, but not all of them showed the correct figure. I doesn't recommend to use NOT IN ( sub query ) for the following reasons:
Strange results when running SQL IN and NOT IN using Redshift
Optimization for Large IN Lists
Consider using EXISTS instead of IN with a subquery
Please find my code here:
WITH helper_table as
(
SELECT "Name",
series,
count(1) as seasons_watched
FROM your_table
GROUP BY 1, 2
)
------------------------------------------------------------
SELECT t1."Name"
FROM
(
SELECT "Name",
count(1) as is_watched_at_least_one_series_of_alpha
FROM helper_table
WHERE series = 'alpha'
GROUP BY 1
) t1
INNER JOIN
(
SELECT "Name",
count(1) as watched_exactly_one_series_so_far
FROM helper_table
GROUP BY 1
HAVING count(1) = 1
) t2
ON t2."Name" = t1."Name"
;
Hope it helps!

Filter out records based on condition SQL

I am trying to filter out some records based on condition but couldn't get the proper results.
Data:
GID OID SID Z
1 1 1 A
1 2 2 B
1 3 3 C
1 2 4 B
Expected Result:
GID OID SID Z
1 1 1 A
1 3 3 C
Here GID, OID can be repeated but not SID.
Need to filter out all records where Z contains 'A' & 'C'
What I have tried:
select distinct GID, OID, SID, Z
from table
where Z ilike ('A') or Z ilike ('C')
but this query will include all record of sample GID records.
Moreover I have also thought of self join but could not frame the query around that.
I think this is the query you need
WITH cte AS (
SELECT
gid, oid, sid, z,
ROW_NUMBER() OVER () AS rn
FROM data
WHERE LOWER(z) LIKE '%a%'
OR LOWER(Z) LIKE '%c%'
)
SELECT gid, oid, sid, z FROM cte c
WHERE NOT EXISTS (
SELECT sid FROM cte t
WHERE t.z = c.z
AND t.sid = c.sid
AND t.rn < c.rn
)
I use ROW_NUMBER to be able to check if a sid value repeats.
Demo

Sort records based on string

Please consider the table below
Id F1 F2
---------------------------
1 Nima a
2 Eli a
3 Arian a
4 Ava b
5 Arsha b
6 Rozhan c
7 Zhina c
I want to display records by sorting COLUMN F2 to display one record from each string category (a,b,c) in order
Id F1 F2
---------------------------
1 Nima a
5 Arsha b
6 Rozhan c
2 Eli a
4 Ava b
7 Zhina c
3 Arian a
NOTE: a,b,c could be anything... it should take one record from one entry and then 2nd from 2nd entry.
I have used join, or group by records but no success.
MySQL version 5.7 – Syed Saqlain
SELECT id, f1, f2
FROM ( SELECT t1.id, t1.f1, t1.f2, COUNT(*) cnt
FROM test t1
JOIN test t2 ON t1.f2 = t2.f2 AND t1.id >= t2.id
GROUP BY t1.id, t1.f1, t1.f2 ) t3
ORDER BY cnt, f2;
https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=8138bd9ab5be36ba534a258d20b2e555
ROW_NUMBER() alternative for lower version of MYSQL. This query will work for version 5.5, 5.6 & 5.7.
-- MySQL (v5.7)
SELECT t.id, t.f1, t.f2
FROM (SELECT #row_no:=CASE WHEN #db_names=d.f2 THEN #row_no+1 ELSE 1 END AS row_number
, #db_names:= d.f2
, d.f2
, d.f1
, d.id
FROM test d,
(SELECT #row_no := 0,#db_names:='') x
ORDER BY d.f2) t
ORDER BY t.row_number, t.f2
Please check from url https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=02dbb0086a6dd7c926d55a690bffbd06
You can use window functions in the order by:
select t.*
from t
order by row_number() over (partition by f2 order by id),
f2;
The row_number() function (as used above) assigns a sequential number starting with 1 to each value of f2.
In older versions of MySQL, you can use a correlated subquery instead:
order by (select count(*) from t t2 where t2.f2 = t.f2 and t2.id <= t.id),
f2;
For performance, you want an index on (f2, id).

Mysql obtain numbers repeat from multiple columns

i've got a database similar to the following SqlFiddle http://sqlfiddle.com/#!9/f30a65/1/0
I need to obtain the group by but the trouble is that the data are on multiple columns...
Eg result expected:
VALUE - COUNT or Group By
13 - 2
11 - 1
Thanks to everyone
If you want to Group By on combine with all column you could use
SELECT value, count(value) as count FROM (
SELECT C1 as value FROM TABLE1
UNION ALL
SELECT C2 as value FROM TABLE1
UNION ALL
SELECT C3 as value FROM TABLE1
UNION ALL
SELECT C4 as value FROM TABLE1
UNION ALL
SELECT C5 as value FROM TABLE1
UNION ALL
SELECT C6 as value FROM TABLE1
) all_col GROUP BY value

How to get all data from a table only for the latest year, while many rows may be associated with that year

Here is the simplified table:
id - company_id - report_year - code
1 - 123456 - 2013 - ASD
2 - 123456 - 2013 - SDF
3 - 123456 - 2012 - ASD
4 - 123456 - 2012 - SDF
I would like to get all codes for the highest report_year available for the specified company_id.
So I should get:
1 - 123456 - 2013 - ASD
2 - 123456 - 2013 - SDF
But I can not hard code WHERE year = 2013, because for some company latest report year may be 2012 or 2009 for example. So I need to get data based on the latest year available.
So far I have query like this:
SELECT id, company_id, report_year, code,
FROM `my_table`
WHERE company_id= 123456
I have tried with some mixtures of group by and max() but I couldn't get what I need, this is the first time I am facing such a request, its confusing.
Any ideas ? I am using mysql.
Use a correlated sub-query to find latest year for a company:
SELECT id, company_id, report_year, code,
FROM `my_table` t1
WHERE company_id = 123456
AND report_year = (select max(report_year)
from `my_table` t2
where t1.company_id = t2.company_id)
You could do this using a join on the same table which returns the max year per company like so:
select my_table.id, my_table.company_id, my_table.report_year, my_table.code
from my_table
inner join (
select max(report_year) as maxYear, company_id
from my_table
group by company_id
) maxYear ON my_table.report_year = maxYear.maxYear
and my_table.company_id = maxYear.company_id
To limit this to a specific company, just add your where clause back:
select my_table.id, my_table.company_id, my_table.report_year, my_table.code
from my_table
inner join (
select max(report_year) as maxYear, company_id
from my_table
where my_table.company_id= 123456
group by company_id
) maxYear ON my_table.report_year = maxYear.maxYear
and my_table.company_id = maxYear.company_id
Often, an anti-join yields better performance than using subqueries:
SELECT t1.id, t1.company_id, t1.report_year, t1.code
FROM `my_table` t1
LEFT JOIN `my_table` t2
ON t2.company_id = t1.company_id AND t2.report_year > t1.report_year
WHERE t1.company_id = 123456 AND t2.report_year IS NULL
For best performance, ensure you have a multi-column index on (company_id, report_year).
You can read more about this technique in the book SQL Antipatterns, which is where I learned it.