Currently, I've got a single set of data in which I want to exclude based on if a condition is meet. The group has a common column reference.
Name Sequence Value
-----------------------------------
Text 1 1
Don 1 30
Text 2 0
Sid 2 240
Florence 2 300
Text 3 200
Casper 3 20
Cat 3 10
Text 4 0
Dem 4 50
Basically any row in which Text is not equal to 0 needs to be excluded be excluded. In addition the rows in which share the same sequence. Expected outcome is to only have data from sequence 2 and 4.
You can try with NOT EXISTS as below-
SELECT Name,
Position,
Value
FROM your_table
WHERE NOT EXISTS (
SELECT Name,Position,Value
FROM your_table
WHERE (Name = 'Text' AND Value = 1)
OR (Position = Value)
)
As you are looking for options other than NOT EXISTS, you can try this below-
SELECT *
FROM your_table
WHERE [Sequence] NOT IN (
SELECT DISTINCT [Sequence]
FROM your_table
WHERE [Name] = 'Text'
AND [Value] <> 0
)
Related
Say I have this table t:
id value
1 1 10
2 2 3
3 1 55
4 1 20
5 2 98
When drawing from t I want to add a column value2 that equals value when id == 2, otherwise 0
I tried
select id, value, max(case when id = 2 then value else 0) from t
but it did not work
Not sure why you included a max in your attempt but based on your description, this is all you should need.
select id, value, case when id = 2 then value else 0 end as value2
from t;
It sounds like you want a conditional window aggregate:
select
id,
value,
max(case when id = 2 then value end) over ()
from t;
I have a SQL table of the following format:
ID Cat
1 A
1 B
1 D
1 F
2 B
2 C
2 D
3 A
3 F
Now, I want to create a table with one ID per row, and multiple Cat's in a row. My desired output looks as follows:
ID A B C D E F
1 1 1 0 1 0 1
2 0 1 1 1 0 0
3 1 0 0 0 0 1
I have found:
Transform table to one-hot-encoding of single column value
However, I have more than 1000 Cat's, so I am looking for code to write this automatically, rather than manually. Who can help me with this?
First let me transform the data you pasted into an actual table:
WITH data AS (
SELECT REGEXP_EXTRACT(data2, '[0-9]') id, REGEXP_EXTRACT(data2, '[A-Z]') cat
FROM (
SELECT SPLIT("""1 A
1 B
1 D
1 F
2 B
2 C
2 D
3 A
3 F""", '\n') AS data1
), UNNEST(data1) data2
)
SELECT * FROM data
(try sharing a table next time)
Now we can do some manual 1-hot encoding:
SELECT id
, MAX(IF(cat='A',1,0)) cat_A
, MAX(IF(cat='B',1,0)) cat_B
, MAX(IF(cat='C',1,0)) cat_C
FROM data
GROUP BY id
Now we want to write a script that will automatically create the columns we want:
SELECT STRING_AGG(FORMAT("MAX(IF(cat='%s',1,0))cat_%s", cat, cat), ', ')
FROM (
SELECT DISTINCT cat
FROM data
ORDER BY 1
)
That generates a string that you can copy paste into a query, that 1-hot encodes your arrays/rows:
SELECT id
,
MAX(IF(cat='A',1,0))cat_A, MAX(IF(cat='B',1,0))cat_B, MAX(IF(cat='C',1,0))cat_C, MAX(IF(cat='D',1,0))cat_D, MAX(IF(cat='F',1,0))cat_F
FROM data
GROUP BY id
And that's exactly what the question was asking for. You can generate SQL with SQL, but you'll need to write a new query using that result.
BigQuery has no dynamic column with standardSQL, but depending on what you want to do on the next step, there might be a way to make it easier.
Following code sample groups Cat by ID and uses a JavaScript function to do one-hot encoding and return JSON string.
CREATE TEMP FUNCTION trans(cats ARRAY<STRING>)
RETURNS STRING
LANGUAGE js
AS
"""
// TODO: Doing one hot encoding for one cat and return as JSON string
return "{a:1}";
"""
;
WITH id_cat AS (
SELECT 1 as ID, 'A' As Cat UNION ALL
SELECT 1 as ID, 'B' As Cat UNION ALL
SELECT 1 as ID, 'C' As Cat UNION ALL
SELECT 2 as ID, 'A' As Cat UNION ALL
SELECT 3 as ID, 'C' As Cat)
SELECT ID, trans(ARRAY_AGG(Cat))
FROM id_cat
GROUP BY ID;
The original table has three not unique columns, where id value separate data by groups:
id name flag
----------------------------
1 Andrey 0
1 Andrey 1
1 Olga 0
1 Sasha 0
2 Masha 1
2 Masha 0
2 Katya 1
2 Vera 0
Here we have two groups of people, where each group has two rows with equal names. I would like to write a select statemets which duplicate name rows with flag 0, if and only if this exact name has 1 flag in the same group.
So, expected result for this data should be:
id name flag
----------------------------
1 Andrey 1
2 Masha 1
because Andrey and Masha are duplicates and they have 0 flag too.
My attempt to select these values is to use query like following:
select * from names
where flag = 1 and id in
(select id from names where flag = 0)
but it's returns Katya row too, what is unexcepted.
You can use EXISTS:
SELECT n.* FROM Names n
WHERE n.flag = 1
AND EXISTS
(
SELECT 1 FROM Names n2
WHERE n.id = n2.id
AND n.name = n2.name
AND n2.flag = 0
)
You can use the intersect operator to get the name which has both the flags.
select name from names where flag = 0
intersect
select name from names where flag = 1
In MySQL, you could do,
select n1.name
from names n1
join names n2 on n1.name = n2.name and n2.flag = 1
where n1.flag = 0
I have an input:
id
1
2
3
4
5
6
7
8
9
10
I want get even and odd columns separately by columns in specified output like this
id col
1 2
3 4
5 6
7 8
9 10
here id and col are separate columns id contains the odd number and col contains the even number for specified input
SELECT MIN(id) as id, MAX(id) as col
FROM YourTable
GROUP BY FLOOR((id+1)/2)
For IDs 1 and 2, (id+1)/2 are 2/2 = 1 and 3/2 = 1.5, respectively, and FLOOR then returns 1 for both of them. Similarly, for 3 and 4, this is 2, and so on. So it groups all the input rows into pairs based on this formula. Then it uses MIN and MAX within each group to get the lower and higher IDs of the pairs.
Joined the table on itself
select *
from yourTable tA
left join yourTable tb on tA.id = (tB.id - 1)
where tA.id % 2 <> 0
If you use SQL you can try:
SELECT CASE WHEN column % 2 = 1
THEN column
ELSE null
END AS odds,
CASE WHEN column % 2 = 2
THEN column
ELSE null
END AS even
FROM yourtable
but not exactl as you ask
To show odd:
Select * from MEN where (RowID % 2) = 1
To show even:
Select * from MEN where (RowID % 2) = 0
Now, just join those two result sets and that's it.
Source
I have a table MOUVEMENTS which has 3 columns :
ID IDREF NUMBER
1 1 5
2 1 3
3 1 4
4 1 2
5 2 1
I'd like to fetch the rows of this table with that constraints :
IDREF = 1
Ordered by ID ASC
and the X first SUM of NUMBER (by IDREF)
I imagine that we will first calculate the SUM. And then we will restrict with that column
ID IDREF NUMBER SUM
1 1 5 5
2 1 3 8
3 1 4 12
4 1 2 2
5 2 1 1
In this case, if we want to have 11, we will take the two first column + the third and we will change the number to have a coherent value.
So the result awaited :
ID IDREF NUMBER SUM
1 1 5 5
2 1 3 8
3 1 3 11
Please note the change in the third line on the NUMBER and SUM column.
Do you know how to achieve that ?
This query should work from sql 2000 to 2008 R2
I've created a solution here which uses a view: http://www.sqlfiddle.com/#!3/ebb01/15
The view contains a running total column for each IDRef:
CREATE VIEW MouvementsRunningTotals
AS
SELECT
A.ID,
A.IDRef,
MAX(A.Number) Number,
SUM (B.Number) RunningTotal
FROM
Mouvements A
LEFT JOIN Mouvements B ON A.ID >= B.ID AND A.IDRef = B.IDRef
GROUP BY
A.ID,
A.IDRef
If you can't create a view then you could create this as a temporary table in tsql.
Then the query is a self join on that view, in order to determine which is the last row to be include based on the Number you pass in. Then a CASE statement ensures the correct value for the last row:
DECLARE #total int
DECLARE #idRef int
SELECT #total = 4
SELECT #idRef = 1
SELECT
A.ID,
A.IDRef,
CASE
WHEN A.RunningTotal <= #total THEN A.Number
ELSE #total - B.RunningTotal
END Number
FROM
MouvementsRunningTotals A
LEFT JOIN MouvementsRunningTotals B ON
A.IDRef = B.IDRef
AND A.RunningTotal - A.Number = B.RunningTotal
WHERE
A.IDRef = #IDRef
AND (A.RunningTotal <= #total
OR (A.RunningTotal > #total AND B.RunningTotal < #total))
You can add more data in the Build Schema box and change the Number in the #total parameter in the Query box to test it.
select id, (select top 1 number from mouvements) as number, idref
from mouvements where idref=1 order by id asc