SELECT Row Values WHERE MAX() is Column Value In GROUP BY Query - sql

How can I select like this? Can I create a User defined Aggregate Function
SELECT Max(A),(SELECT TOP 1 FROM TheGroup Where B=Max(A)) FROM MyTable
where MyTable as Shown Below
A B C
--------------
1 2 S
3 4 S
4 5 T
6 7 T
I want a Query Like this
SELECT MAX(A),(B Where A=Max(A)),C FROM MYTable GROUP BY C
I'm Expecting the result as below
MAX(A) Condition C
-----------------------
3 4 S
6 7 T

SELECT A,B,C FROM
(SELECT *, ROW_NUMBER() OVER (PARTITION BY C ORDER BY A DESC) RN FROM MyTable)
WHERE RN = 1
(this query will always return only one row per C value)
OR
WITH CTE_Group AS
(
SELECT C, MAX(A) AS MaxA
FROM MyTable
GROUP BY C
)
SELECT g.MaxA, t.B, g.C
FROM MyTable t
INNER JOIN CTE_Group g ON t.A = g.MaxA AND t.C = g.C
(if there are multiple rows that have same Max(A) value - this query will return all of them)

Try Following Query :
SELECT TABLE1.A , TABLE2.B , TABLE1.C
FROM
(
SELECT MAX(A) AS A,C
FROM MYTable
GROUP BY C
) AS TABLE1
INNER JOIN
(
SELECT *
FROM MYTable
) AS TABLE2 ON TABLE1.A = TABLE2.A
SQLFIDDLE
you can do it by simple join query . join query always run faster then In query . Join query run only one time at the time of execution of the query . we can archive same result by using IN query .

SELECT t1.*
FROM YourTable t1
Left Outer Join YourTable t2 on t1.C=t2.C AND t1.A < t2.A
WHERE t2.A is null

how about this:
SELECT *
FROM MyTable
WHERE A IN (SELECT MAX(A) FROM MyTable GROUP BY C)

SELECT Max(A)
FROM MyTable
Where B=(SELECT Max(A) FROM MyTable)
update:
SELECT *
FROM MyTable
Where B=(SELECT Max(A) FROM MyTable)
update 2:
SELECT DISTINCT A, B
FROM MyTable
Where A=(SELECT Max(A) FROM MyTable GROUP BY C)
update 3:
ok, I think I understand what you're looking for now.. How about this:
SELECT *
FROM MyTable
Where A in (SELECT Max(A) FROM MyTable GROUP BY C)

WITH
cte AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY cola desc) AS Rno,
*
FROM
tbl
)
SELECT top 1
cola,colb
FROM
cte
order by Rno
Then try it:
WITH
cte AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY col3 ORDER BY col1 desc) AS Rno,
*
FROM
tbl
)
SELECT
col1,col2,col3
FROM
cte
WHERE Rno=1

Related

WITH clause in HIVE

In below code temp1 is used 2 times, so hive will be execute the select query in temp1 twice? or just once?
with temp1(
select distinct b as b, f, t1.id as id,
from
table1 t1
join
table2 t2 on (t1.id=t2.id)
),
agg_tbl as
(
select
max(abc) as maxabc,
tbl.t
from(
select
count(*) as cnt, b, f
from
temp1
group by
b, f
) tbl group by tbl.t
),
class_tbl as
(select
case
when bp = 1 then 'abc'
when bp = 2 then 'xyz'
end as class,
bp
from
( select
count(b) as bcount, bp
from
temp1
group by bp
)tbl
)
If that is the case, then using temporary tables will make sense.
Thanks.

How do I count three different distinct values and group on an ID in MS-Access?

So I know MS-Access does not allow SELECT COUNT(DISTINCT....) FROM ..., but I am trying to find a more viable alternative to the usual standard of
SELECT COUNT(*) FROM (SELECT DISTINCT Name FROM table1)
My problem is I am trying to do three separate Count functions and group them on ID. If I use the method above, it is giving me the total unique value count for the whole table instead of the total count for only the value of ID. I tried doing
(SELECT COUNT(*) FROM (SELECT DISTINCT Name FROM table1 as T2
WHERE T2.ColumnA = T1.ColumnA)) As MyVal
FROM table1 as T1
but it tells me I need to specify a value for T1.ColumnA.
The SQL query I am trying to accomplish is this:
SELECT ID
COUNT(DISTINCT ColumnA) as CA,
COUNT(DISTINCT ColumnB) as CB,
COUNT(DISTINCT ColumnC) as CC
FROM table1
GROUP BY ID
Any ideas?
You can use subqueries. Assuming you have a table where each id occurs once:
select (select count(*)
from (select columnA
from table1 t1
where t1.id = t.id
group by columnA
) as a
) as num_a,
(select count(*)
from (select columnB
from table1 t1
where t1.id = t.id
group by columnB
) as b
) as num_b,
(select count(*)
from (select columnC
from table1 t1
where t1.id = t.id
group by columnC
) as c
) as num_c
from <table with ids> as t;
I'm not sure if you'll think this is "viable".
EDIT:
This makes it even more complicated . . . it suggests that MS Access doesn't support correlation clauses more than one level deep (might you consider switching to another database?).
In any case, the brute force way:
select a.id, a.numA, b.numB, c.numC
from ((select id, count(*) as numA
from (select id, columnA
from table1 t1
group by id, columnA
) as a
) as a inner join
(select id, count(*) as numB
from (select id, columnB
from table1 t1
group by id, columnB
) as b
) as b
on a.id = b.id
) inner join
(select id, count(*) as numC
from (select id, columnC
from table1 t1
group by id, columnC
) as c
) c
on c.id = a.id;

Randomly Assign Records From One Table to Another

I have two tables.
T1
id,date,item,channel
T2
id,date,item,channel
In T2 the id and date columns are NULL. I want to randomly assign an id and date from T1 to each row in T2. Also, T2 is much smaller than T1.
Any ideas how to do this? I'm on Teradata 13.
I was originally thinking something like this:
sel count(*) from t2 ;
--507
select *
from (sel a.*, RANDOM(1,507) as r1 from t1) a
inner join (sel b.*, RANDOM(1,507) as r1 from t2) b
on a.r1 = b.r1
The problem is I'll need to automatically assign the count of t2 as the upper bound of random.
Assign a ROW_NUMBER based on a RANDOM sort and join on that:
select *
from
(
select dt.*, row_number() over (order by t1.r) as rn
from
(
select t1.*, RANDOM(1,1000000) as r from t1
) as dt
) as a
join
(
select dt.*, row_number() over (order by t1.r) as rn
from
(
select t2.*, RANDOM(1,1000000) as r from t2
) as dt
) as b
on a.rn = b.rn

SQL Server. Delete from Select

I am using SQL Server 2012, and have the following query. Let's call this query A.
SELECT a.col, a.fk
FROM Table1 a
INNER JOIN (
select b.col
from Table1 b
group by b.col
having count(*) > 1)
b on b.col = a.col
I want to delete only the rows returned from query A, specifically rows that match the returned col AND fk
I am thinking of doing the following, but it will only delete rows that match on the col.
delete from Table1
where col in (
SELECT a.col
FROM Table1 a
INNER JOIN (
select b.col
from Table1 b
group by b.col
having count(*) > 1)
b on b.col = a.col)
)
Use delete from Join syntax
delete t1
from table1 t1
INNER JOIN (SELECT a.col, a.fk
FROM Table1 a
INNER JOIN (
select b.col
from Table1 b
group by b.col
having count(*) > 1)
b on b.col = a.col) t2
ON t1.col1=t2.col1 and t1.fk=t2.fk
you can combine col and fk fields to be another unique filed to retrieve wanted rows
delete from Table1
where cast(col as varchar(50))+'//'+cast(fk as varchar(50)) in (
SELECT cast(a.col as varchar(50))+'//'+cast(a.fk as varchar(50))
FROM Table1 a
INNER JOIN (
select b.col
from Table1 b
group by b.col
having count(*) > 1)
b on b.col = a.col)
)
You can express Query A like this:
SELECT col, fk
FROM (
SELECT a.col, a.fk, COUNT(*) OVER (PARTITION BY a.col) AS [count]
FROM Table1 a
) counted
WHERE [count] > 1
Which leads to a nice way to do the DELETE using a CTE:
;WITH ToDelete AS (
SELECT a.col, a.fk, COUNT(*) OVER (PARTITION BY a.col) AS [count]
FROM Table1 a
)
DELETE FROM ToDelete
WHERE [count] > 1
This does give the same result as the DELETE statement in your question though.
If you want to delete all but one row with the duplicate col value you can use something like this:
;WITH ToDelete AS (
SELECT a.col, a.fk
, ROW_NUMBER() OVER (PARTITION BY a.col ORDER BY a.fk) AS [occurance]
FROM Table1 a
)
DELETE FROM ToDelete
WHERE [occurance] > 1
The ORDER BY clause will determine which row is kept.

compare two tables on SQL server with result to show which column from its associated table

I need to compare two tables on SQL server.
table1
id value
3 5
table2
id value
8 6
SELECT *
FROM
(
SELECT a.id AS a_id, a.value AS a_value
FROM [table1] as a
UNION ALL
SELECT b.id AS b_id, b.value AS b_value
FROM [table2] as b
) tmp
GROUP BY tmp.a_id, tmp.a_value
HAVING COUNT(*) = 1
ORDER BY tmp.a_id
I get result:
a_id a_value
3 5
8 6
I need to know which column is from which table, e.g.
a_id a_value b_id b_value
3 5 8 6
Any help would be appreciated !
Thanks !
What about:
SELECT *
FROM (
SELECT a.id, a.value, 'Table1' AS TableName
FROM [table1] as a
UNION ALL
SELECT b.id, b.value, 'Table2' AS TableName
FROM [table2] as b
) tmp
GROUP BY tmp.id, tmp.value, tmp.TableName
HAVING COUNT(*) = 1
ORDER BY tmp.id
You could add a column for tbl. Something like:
SELECT
m.id
,m.value
INTO #tmp
FROM
(
SELECT a.id AS id, a.value AS value
FROM [table1] as a
UNION ALL
SELECT b.id AS id, b.value AS value
FROM [table2] as b
) m
GROUP BY
m.id
,m.value
HAVING COUNT(*) = 1
CREATE CLUSTERED INDEX ix_tmpidvalue ON #tmp
(
id ASC
,value ASC
)
SELECT *
FROM
(
SELECT a.id AS id, a.value AS value, 'a' tbl
FROM [table1] as a
UNION ALL
SELECT b.id AS id, b.value AS value, 'b' tbl
FROM [table2] as b
) tmp
WHERE EXISTS
(
SELECT 1
FROM #tmp n
WHERE tmp.id = n.id
AND tmp.value = n.value
)
ORDER BY tmp.id