Compare values within a column per partition - sql

I'm looking to compare values within a column per partition and see if they match but I'm not sure how to go about it.
A
B
C
22
900
0
24
900
0
22
006
1
24
006
1
Basically I want to check if the values for column A match the values for column A per partition of C.
So in this case the values for column A in the first partition of C (value 0) are 22 and 24
the values for column A in the second partition of C (value 1) are also 22 and 24. in this case there is a match. Is there a way to complete this comparison (and possibly put it in a new column with 1=match and 0=no match?

So trying to Help, I tried this on Postgres.
I think you'll find a way to adapt this sql to terrada's.
-- Lets create a table of your data (and more)
create table mydata (a integer, b integer, c integer);
insert into mydata (a, b, c) values (22, 900, 0);
insert into mydata (a, b, c) values (24, 900, 0);
insert into mydata (a, b, c) values (22, 900, 1);
insert into mydata (a, b, c) values (24, 900, 1);
insert into mydata (a, b, c) values (22, 900, 2);
insert into mydata (a, b, c) values (22, 900, 3);
insert into mydata (a, b, c) values (21, 900, 2);
-- Here below the solution
SELECT c,
CASE
when COUNT(c) OVER(PARTITION BY conc) = 1 Then 0
when COUNT(c) OVER(PARTITION BY conc) > 1 Then 1
END as flag
FROM
( SELECT c, STRING_AGG (a::text, ',') conc
FROM mydata
GROUP BY c ) sub1
I guess now you have idea how to do ;)

Related

Getting SQL rows where >= 1 row have a certain value in another column

I've seen similarly worded questions, and I may be phrasing it wrong, but take the following example table:
a
b
1
5
2
6
3
7
1
8
2
8
2
9
1
10
2
10
3
10
And say I know beforehand that I have a values [1,2]. How can I get all values of b that the a values share? In the above, the result would be [8, 10]. If I had [1,3] for a, then I would get [10]. If I had [2] for a, I would get [6,8,9,10]
I imagine it would start something like SELECT b from tablename WHERE ...
You can use intersect
Schema and insert statements:
create table test(a int, b int);
insert into test values(1, 5);
insert into test values(2, 6);
insert into test values(3, 7);
insert into test values(1, 8);
insert into test values(2, 8);
insert into test values(2, 9);
insert into test values(1, 10);
insert into test values(2, 10);
insert into test values(3, 10);
Query1:
select b from test where a=1
intersect
select b from test where a=2
Output:
b
8
10
Query2:
select b from test where a=1
intersect
select b from test where a=3
Output:
b
10
Query3:
select b from test where a=2
Output:
b
6
8
9
10
db<>fiddle here
Create a CTE that returns the values of a that you want and filter the table for these values only.
Then group by b and in the HAVING clause filter the resultset so that only values of b that are associated to the values of a that you want are returned:
WITH cte(a) AS (VALUES (1), (2))
SELECT b
FROM tablename
WHERE a IN cte
GROUP BY b
HAVING COUNT(*) = (SELECT COUNT(*) FROM cte);
See the demo.

Return sum of matching rows as a separate field

I want to write a SQL query that will give me field C as the sum of field B for each unique row in field A. So for X, field B has 10 and 35, therefore field C would should 45 for both rows of X.
I need a query that will return the entire result as one "dataset" like below (instead of a query that just gives me field C). I think maybe I would need 2 queries? One to grab A and B results and then a 2nd query to select from results and SUM(expression) for field C?
You can use a window function SUM()OVER() or a SUM() within a subquery like
CREATE TABLE T(
A VARCHAR(10),
B INT
);
INSERT INTO T VALUES
('X', 10),
('Y', 15),
('Z', 40),
('X', 35),
('Y', 10);
SELECT *,
(SELECT SUM(B) FROM T WHERE A = TT.A) C,
SUM(B) OVER(PARTITION BY A) AnotherC
FROM T TT;
Here is a live demo
Looks like Sami posted while I was doing my copy/paste :) but here's a similar solution:
Declare #test Table
(
a varchar(10),
b int
)
Insert Into #test (a, b) Values ('X', 10);
Insert Into #test (a, b) Values ('Y', 15);
Insert Into #test (a, b) Values ('Z', 40);
Insert Into #test (a, b) Values ('X', 35);
Insert Into #test (a, b) Values ('Y', 10);
Select t.a, t.b, (Select sum(sq.b) From #test sq Where sq.a = t.a) as c
From #test t
The below given query is enough.
select A,B, SUM(B) OVER(PARTITION BY A) AS C FROM TABLE

Generate Alpha numeric series in SQL Server 2008

Can anyone please help me on this?
I want to generate a alpha numeric series like A.1, A.2, A.3, A.4, B.1, B.2 which should increment automatically if I add new row.
I have a columns A and B which will be look like below.
A B
-----
1 A
1 A
1 A
1 A
2 B
2 B
3 C
3 C
3 C
The result must be look like below:
A B C
-----------
1 A A.1
1 A A.2
1 A A.3
1 A A.4
2 B B.1
2 B B.2
3 C C.1
3 C C.2
3 C C.3
The below query can return your expected result.
SELECT A, B, B + '.' + CAST(ROW_NUMBER() OVER (PARTITION BY B ORDER BY A) AS VARCHAR) AS C
FROM TableName
Generating the Alpha numeric series is difficult. Using ROW_NUMBER() in computed column is also not possible. So for your case view is the right choice to achieve your expectation:
CREATE VIEW dbo.vw_MyAlphaNumbericOrder AS
SELECT A, B, B + '.' + CAST(ROW_NUMBER() OVER (PARTITION BY B ORDER BY A) AS VARCHAR) AS C
FROM dbo.TableName
So when ever you are inserting a new record, then SELECT * FROM dbo.vw_MyAlphaNumbericOrder will return with the alpha numeric series as column C.
Sample execution with the given sample data:
DECLARE #TestTable TABLE (A INT, B VARCHAR (2));
INSERT INTO #TestTable (A, B) VALUES
(1, 'A'),
(1, 'A'),
(1, 'A'),
(1, 'A'),
(2, 'B'),
(2, 'B'),
(3, 'C'),
(3, 'C'),
(3, 'C');
SELECT A, B, B + '.' + CAST(ROW_NUMBER() OVER (PARTITION BY B ORDER BY A) AS VARCHAR) AS C
FROM #TestTable
We can achieve this by below statement:
Select A,B,concat(B,'.',cast(row_number() over(partition by B order by B) as char(32))) as C
1.row_number() over (Partition by)-- will generate new row no. in each category of column B.
2.Cast -- will change the numeric value to character value where 32 specifies the length of data the field can hold
3. Concat-- will concatenate the required columns to create Alpha-numeric string

How to get value without subqueries (on SQL-Server)?

I have the following table on SQL Server:
ID Num
1 A
2 B
2 B
3 C
3 C
4 C
(Num is a numeric column - A, B, and C are standins for numeric values, for the purpose of this question)
How to get the value of A+B+C+C without using subqueries and CTE?
A - for 1, B - for 2, C - for 3, C - for 4.
The answer seems to sum(distinct Num), but distinct is by ID field!
Demo table:
create table test (ID int, Num int);
insert into test values (1, 10);
insert into test values (2, 100);
insert into test values (2, 100);
insert into test values (3, 1000);
insert into test values (3, 1000);
insert into test values (4, 1000);
The correct answer is 10+100+1000+1000 = 2110.
A random guess, using CTE to avoid the pointless subquery restriction:
With X as (Select Distinct Id, No From Test)
Select
Sum(No)
From X
Or using a derived table (which works in SQL 2000):
Select
Sum(No)
From (
Select Distinct
Id,
No
From
Test
) a;
http://sqlfiddle.com/#!3/77a6e/6
The solution:
select cast(sum(distinct Num + cast(0.00001 as number(38,19))/ID) as number(18,2))

Adding a custom column to SQL query

Lets say I have a DB built like this:
NUM VALUE
1 3.51
2 hello
1 3.487
2 goodbye
1 32.4
2 foo
what I need to do to add another column in which all the values having num "2" will be in.
e.g.
NUM VALUE value2
1 3.51 hello
1 3.487 goodbye
1 32.4 foo
any idea how I can do this?
thanks!
In this example I am using SQLite, where the table Source already has a built-in rowid. Depending on the database you are using, you may need to add your own auto-incrementing integer column (i.e., integer primary key), but the idea is the same.
CREATE TABLE Source (num, value);
INSERT INTO Source (num, value) VALUES (1, 3.51);
INSERT INTO Source (num, value) VALUES (2, 'hello');
INSERT INTO Source (num, value) VALUES (1, 3.487);
INSERT INTO Source (num, value) VALUES (2, 'goodbye');
INSERT INTO Source (num, value) VALUES (1, 32.4);
INSERT INTO Source (num, value) VALUES (2, 'foo');
"1","3.51"
"2","hello"
"1","3.487"
"2","goodbye"
"1","32.4"
"2","foo"
SELECT a.num, a.value, b.value
FROM Source a
INNER JOIN Source b ON a.rowid = b.rowid - 1
WHERE a.num = 1 AND b.num = 2
"1","3.51","hello"
"1","3.487","goodbye"
"1","32.4","foo"