Selecting an actual MIN value instead of NULL in SQL query - tsql

From this table:
Select * into #tmp from (
select 'a' A, 'b' B, NULL C union all
select 'aa' A, 'ab' B, 1 C union all
select 'aaa' A, 'bbb' B, 2 C ) x
I'd like to get this result:
A B Val
a b 1
aa ab 1
aaa bbb 2
That is, take the non-null min value and replace the NULL.
I suppose I could join the table to a filtered version of itself where no nulls appear. But that seems overkill. I thought this might be able to be done in the MIN Aggregate clause itself.
Any ideas would be helpful, thanks!

declare #null int
select #null = MIN(c) from #tmp
select A,
B,
ISNULL(c,#null) as val1
from #tmp
or
select A,
B,
ISNULL(c,(select MIN(c) from #tmp)) as val1
from #tmp

EDIT: I wrote "You want something like ISNULL(c, MIN(c)) but that's not possible."
But I'm wrong, it is possible. I was missing something in my syntax, so #kiki47's answer is exactly what you are asking for.
I wouldn't phrase it as "I suppose I could join the table to a filtered version of itself where no nulls appear," but more or less you can get the min and the use it.
In one go:
WITH cte AS (
SELECT MIN(c) minVal FROM #tmp WHERE c IS NOT NULL
)
SELECT a, b, ISNULL(c, cte.minVal)
FROM #tmp
CROSS JOIN cte
or maybe simpler (but may optimize to the same thing):
DECLARE #minVal INTEGER
SELECT #minVal = MIN(c) FROM #tmp WHERE c IS NOT NULL
SELECT a, b, ISNULL(c, #minVal) FROM #tmp

Related

PostgreSQL: How to treat upper/lower case as duplicates, not change case and keep earlier entry?

In the following, 'abc' and 'ABC' should be considered duplicates. But I want to keep original casing and I want to take the earlier dated entry. So that I end up with: abc, 2021-06-01
I thought this would work, but it doesn't:
select t.s, max(t.d) from
(
select 'abc' s, '2021-06-01'::date d union all
select 'ABC' s, '2021-06-21'::date d
) t
group by lower(t.s)
throws this error: Invalid operation: column "t.s" must appear in the GROUP BY clause or be used in an aggregate function;
What am I missing here?
Thanks!
You can use the PostgreSQL-specific DISTINCT ON construct.
select distinct on (lower(t.s)) t.s, t.d from
(
select 'abc' s, '2021-06-01'::date d union all
select 'ABC' s, '2021-06-21'::date d
) t
order by lower(t.s), d asc;
If you want something more standard SQL, you could use a window function to add a row number, then filter on that row number:
select * from (
select *, row_number() over (partition by lower(t.s) order by t.d) from
(
select 'abc' s, '2021-06-01'::date d union all
select 'ABC' s, '2021-06-21'::date d
) t
) t2 where row_number =1;

T-SQL select all IDs that have value A and B

I'm trying to find all IDs in TableA that are mentioned by a set of records in TableB and that set if defined in Table C. I've come so far to the point where a set of INNER JOIN provide me with the following result:
TableA.ID | TableB.Code
-----------------------
1 | A
1 | B
2 | A
3 | B
I want to select only the ID where in this case there is an entry for both A and B, but where the values A and B are based on another Query.
I figured this should be possible with a GROUP BY TableA.ID and HAVING = ALL(Subquery on table C).
But that is returning no values.
Since you did not post your original query, I will assume it is inside a CTE. Assuming this, the query you want is something along these lines:
SELECT ID
FROM cte
WHERE Code IN ('A', 'B')
GROUP BY ID
HAVING COUNT(DISTINCT Code) = 2;
It's an extremely poor question, but you you probably need to compare distinct counts against table C
SELECT a.ID
FROM TableA a
GROUP BY a.ID
HAVING COUNT(DISTINCT a.Code) = (SELECT COUNT(*) FROM TableC)
We're guessing though.

crystal report hierachical grouping options if part is repeat

I encounter a question about crystal report how to group by ?
I have a table named Part
Part_ID Parent_Part_ID
B A
c A
A NULL
C B
D B
E C
F C
A is a top part, B,C,D not only sub part but also are parent part, E,F are lowest sub part.
Now ,I need to show From Parent_part to Part with Levels,Like This
How Can I show this format data in Crystal report
I try use hierachical grouping options ,but the result is not i want
I need the result is:
A
B
C (shold be show even the part have two parent part)
E
F
D
C
E
F
SOLVED!
Tried menu voice called hierachical grouping options and specified the field that links each record to his parent.
The result should look similar to this:
A
B
C
E
F
D
C
E
F
But Crystal Reports Hierarchies take each record just once, and don't care if same element should be under two parents.
So i made a query-hack, creating hierarchy directly in the data using a JOIN on the same table based on Parent Item
DECLARE #t TABLE (Part_ID varchar(1), Parent_Part_ID varchar(1) );
insert into #t
SELECT 'B' , 'A'
UNION SELECT 'C' , 'A'
UNION SELECT 'A' , NULL
UNION SELECT 'C' , 'B'
UNION SELECT 'D' , 'B'
UNION SELECT 'E' , 'C'
UNION SELECT 'F' , 'C'
SELECT
t1.Part_ID as t1,
t2.Part_ID as t2,
t3.Part_ID as t3,
t4.Part_ID as t4
FROM #t t1
LEFT JOIN #t t2 on t1.Part_ID = t2.Parent_Part_ID
LEFT JOIN #t t3 on t2.Part_ID = t3.Parent_Part_ID
LEFT JOIN #t t4 on t3.Part_ID = t4.Parent_Part_ID
WHERE t1.Parent_Part_ID is null
and removed hierarchical grouping options, just created 3 groups on t1, t2, t3 using header for each group and using details for t4.
The result is, as needed,
A
B
C
E
F
D
C
E
F
Here the .rpt if someone needs it.

Browse two tables using a cursor

In my procedure I have two tables with the same data. I go through my first table through a cursor. Which compares with the second table that I find much the same data. What if, for example in my table_1 I have ten in my data and I have 12 data table2 how to detect missing data in my two table_1 which is traversed by the cursor?
Thx.
Sounds very much like you'd be better off using the MINUS operator.
SELECT a, b, c
FROM table1
MINUS
SELECT a, b, c
FROM table2
This will show you all results that exist in table1 which are not present in table2. In order to show discrepancies both ways, you could do something like this:
SELECT z.*, 'In table1, not in table2' problem_description
FROM (
SELECT a, b, c
FROM table1
MINUS
SELECT a, b, c
FROM table2
) z
UNION ALL
SELECT z.*, 'In table2, not in table1' problem_description
FROM (
SELECT a, b, c
FROM table2
MINUS
SELECT a, b, c
FROM table1
) z
SQL Fiddle for this answer

MySQL: Only output some values once

I think I have done this before, but it could also be a function of PHP. What I would like is to do a MySQL query (in a MySQL client, not PHP) and get for example
Foo A
B
C
Bar B
D
E
Instead of
Foo A
Foo B
Foo C
Bar B
Bar D
Bar E
This would of course only make sence if it was ordered by that first column. Not sure if it is possible, but like I said, I mean to remember to have done this once, but can't remember how or if it was through some PHP "magic"...
Update: Suddenly remembered where I had used it. What i was thinking of was the WITH ROLLUP modifier for GROUP BY. But I also discovered that it doesn't do what I was thinking here, so my question still stands. Although I don't think there is a solution now. But smart people have proved me wrong before :P
Update: Should probably also have mentioned that what I want this for is a many-to-many relationship. In the actual select Foo would be the first name of an attendee and I would also want last name and some other columns. The A, B, C, D, E are options the attendee has selected.
attendee (id, first_name, last_name, ...)
attendees_options (attendee_id, option_id)
option (id, name, description)
This will give you
Foo A,B,C
Bar B,D,E
SELECT column1, GROUP_CONCAT(column2) FROM table GROUP BY column1
Tested this in SQL Server, but I think it will translate to MySQL.
create table test (
id int,
col1 char(3),
col2 char(1)
)
insert into test
(id, col1, col2)
select 1, 'Foo', 'A' union all
select 2, 'Foo', 'B' union all
select 3, 'Foo', 'C' union all
select 4, 'Bar', 'D' union all
select 5, 'Bar', 'E' union all
select 6, 'Bar', 'F'
select case when t.id = (select top 1 t2.id
from test t2
where t2.col1 = t.col1
order by t2.col1, t2.col2)
then t.col1
else ''
end as col1,
t.col2
from test t
order by t.id
drop table test