Multiple condition sum with '%_total' - sql-server-2008

I am aiming to produce code that generates an independent total check. As per the below table:
column1 Column2 Column3 value independent total check
A B c1 10 Null
A B c2 11 Null
A B C_total 21 21
x y z1 10 Null
x y z2 20 Null
x y z_total 30 30
I am trying to employ a conditional sum, but with no success! What I have at the moment is:
IF OBJECT_ID('tempdb..#Temp') IS NOT NULL DROP Table #Temp
select t2.Column1, t2.Column2, t2.Column3,t2.value,
sum (case when (t2.column3 like '%_Total%' and t2.T_desk not like '%Total%') then t2.Value else Null end) over (partition by t2.Column2) as "independent_total_check"into #Temp from #sometemptable
This does not seem to be working properly?! How do I sum the constituents and generate a subtotal? Thank you so much in advance!

Related

Use previous row result when current row is null

I have a table that has daily records of transactions and some rows are missing data which will make plotting a daily graph inconsistent.
I want a query to use the last row result when the current one is null so that it can look something like this:
The structure of my table looks like this:
I have tried working on this query to select the previous row and update the current row if it is null but is not dynamic.
SELECT BALANCE
FROM tbl_batch_balances_null
WHERE id =
(select min(id)
from tbl_batch_balances_null where id < '2' and balance is not null)
Schema (MySQL v5.7)
DROP TABLE IF EXISTS alfie;
CREATE TABLE alfie
(id INT AUTO_INCREMENT PRIMARY KEY,
store CHAR(1) NULL,
product INT NULL
);
INSERT INTO alfie VALUES
( 7,'a',3),
( 8,null,null),
( 9,null,null),
(10,null,null),
(11,'a',1),
(12,'a',1),
(13,'a',1),
(14,null,null),
(15,null,null),
(16,'b',2),
(17,null,null),
(18,null,null),
(19,null,null);
Query #1
SELECT a.id,
COALESCE(a.store, c.store) store,
COALESCE(a.product,c.product) product
FROM alfie a
LEFT
JOIN
( SELECT x.*,
MAX(y.id) y_id
FROM alfie x
JOIN alfie y
ON y.id < x.id
AND y.store IS NOT NULL
WHERE x.store IS NULL
GROUP
BY x.id
) b
ON b.id = a.id
LEFT
JOIN alfie c
ON c.id = b.y_id
ORDER
BY id;
id
store
product
7
a
3
8
a
3
9
a
3
10
a
3
11
a
1
12
a
1
13
a
1
14
a
1
15
a
1
16
b
2
17
b
2
18
b
2
19
b
2
View on DB Fiddle

SQL Query - Find Duplicates with a Different Key

I have the following data:
id userid name group
1 1 A x
2 1 A y
3 1 A z
4 2 B x
5 2 B y
6 3 C y
7 4 D x
8 5 E x
9 5 E z
10 6 F x
I want to find those records that meet all this condition:
Select all rows where the a userid belongs to a group other than y but the userid also belongs to group y.
The resulting dataset will be as follows:
id userid name group
1 1 A x
3 1 A z
4 2 B x
If you see, it has resulted in two records for userid a because these are two two records belong to groups other than y but the userid 1 also belongs to group y. Same for userid 2.
I have been breaking my head on how to get this in an SQL statement but not even close to a solution.
Any help is appreciated.
Use a join:
SELECT t1.*
FROM mytable t1
INNER JOIN mytable t2
ON t1.user_id = t2.user_id AND t1.group <> t2.group AND t2.group = 'y'
I think that would be the fastest query (but please feel free to try the other solutions as well).
Add an index on user_id if not already there and maybe play with some other indexes as well (maybe a composite index on group and user_id can be utilized)
Use exists
select *
from MyTable a2
where name_group <> 'y'
and exists (select 1
from MyTable a2
where a2.name_group = 'y'
and a2.userid = a1.userid)
You can get all the users that meet the condition using aggregation and having:
select userid
from t
group by userid
having sum( group = 'y' ) > 0 and
sum( group <> 'y') > 0;
I leave it to your to put this into a query to get all the original rows.

SQL Select rows where col1 or col2 equals variable

So I want to select rows from table where col1 or col2 equals to variable, but if there is already row selected where col1 equals to variable (variable X) and col2 is anything else (variable Y) then it won't select another row where col2 equals to variable X and col1 equals to that variable Y. Everything ordered by column TIME descending.
Let's say this is my table:
COL1 COL2 TIME COL4
1 2 0 A
1 2 1 B
2 1 2 C
1 3 3 D
3 1 4 E
4 2 5 F
3 4 6 G
1 2 7 H
4 1 8 I
And let's say that variable X equals to 1, then I want to have these rows:
COL1 COL2 TIME COL4
4 1 8 I
1 2 7 H
3 1 4 E
So it won't show me this row
COL1 COL2 TIME COL4
2 1 2 C
because there is already a combination where col1/col2 is 2/1 or 1/2.
Sorry if I explained it in a bad way, but I can't think of better explanation.
Thank you guys.
Making a couple of key assumptions...
SELECT a.*
FROM my_table a
JOIN
( SELECT MAX(time) time
FROM my_table
WHERE 1 IN (COL1,COL2)
GROUP
BY LEAST(col1,col2)
, GREATEST(col1,col2)
) b
ON b.time = a.time;
EDIT: I posted this answer when it was thought that OP's database was SQL Server. But as it turns out, the database is MySQL.
I think this query should do it:
select t.col1, t.col2, t.time, t.col4
from (select t.*,
row_number() over (
partition by
case when col1 < col2 then col1 else col2 end,
case when col1 < col2 then col2 else col1 end
order by time desc) as rn
from tbl t
where t.col1 = x or t.col2 = x) t
where t.rn = 1
order by t.time desc
The key part is defining the row_number partition by clause in such a way that (1, 2) is considered equivalent to (2, 1), which is what the case statements do. Once the partitioning works correctly, you just need to keep the first row of every "partition" (where t.rn = 1) to exclude duplicate rows.

How to retrieve complete data from two tables based on user_name along with max date in Hive

For example I have a table A and B with the following data:
A:
user_name date1 count1 count2
X 15 1 1
X 30 1 3
Y 04 1 3
B:
user_name date1 count3 count4 status
X 15 11 1 Y
X 30 13 3 N
Y 04 16 3 NA
How to join these 2 tables for each feedname with max date.
I need the output like these:
username date1 count1 count4 status
X 30 1 3 N
like these way.
Can anyone plz help in these situation.
Since according to your comment every combination (user_name, date1) exists in both tables, you can use e.g.
select a.*, b.count3, b.count4, b.status
from tableA as a
join tableB as b
on a.user_name = b.user_name and
a.date1 = b.date1
where not exists
(select 1 from tableA as a1
where a1.user_name = a.user_name
and a1.date1 > a.date1);
You want to have an index on (user_name, date1) to speed it up.
As a side note: If every entry in tableA has exactly 1 entry in tableB and vice-versa (it's not clear from your description if that is the case, but it looks like it), and thus (user_name, date1) would be a primary key in both tables, you absolutely should add the columns count3, count4 and status to tableA and get rid of tableB. You can still use the above code (without join) to find only the max entry per user.

SQL statement for querying with multiple conditions including 3 most recent dates

I need help in finding the rows that correspond to the most recent date, the next most recent and the one after that, where some condition ABC is "Y" and group it by a column name XYZ ASC but XYZ can appear multiple times. So, say XYZ is 50, then for the rows in the three years, the XYZ will be 50. I have the following code that executes but returns only two rows out of thousands which is impossible. I tried executing just the date condition but it returned dates that were less than or equal to MAX(DATE)-3 as well. Don't know where I am going wrong.
select * from money.cash where DATE =(
select
MAX(DATE)
from
money.cash
where
DATE > (select MAX(DATE)-3 from money.cash)
)
GROUP BY XYZ ASC
having ABC = "Y";
The structure of the table is as follows (only a schematic, not the real thing).
Comp_ID DATE XYZ ABC $$$$ ....
1 2012-1-1 10 Y SOME-AMOUNT
2 2011-1-1 10 Y
3 2006-1-1 10 Y
4 2011-1-1 20 Y
5 2002-1-1 20 Y
6 2000-1-1 20 Y
7 1998-1-1 20 Y
The desired o/p would be the first three rows for XYZ=10 in ascending order and the most recent 3 dates for XYZ=20.
LAST AND IMPORTANT-This table's values keeps changing as new data comes in. So, the o/p(which will be in a new table) must reflect the dynamics in the 1st/original/above TABLE.
MySQL doesn't have functionallity that is friendly to greatest-n-per-group queries.
One option would be...
- Find the MAX(Date) per group (XYZ)
- Then use that result to find the MAX(Date) of all records before that date
- Then do it again for all records before that date
It's really innefficient, but MySQL hasn't got the functionality required to do this efficiently. Sorry...
CREATE TABLE yourTable
(
comp_id INT,
myDate DATE,
xyz INT,
abc VARCHAR(1)
)
;
INSERT INTO yourTable SELECT 1, '2012-01-01', 10, 'Y';
INSERT INTO yourTable SELECT 2, '2011-01-01', 10, 'Y';
INSERT INTO yourTable SELECT 3, '2006-01-01', 10, 'Y';
INSERT INTO yourTable SELECT 4, '2011-01-01', 20, 'Y';
INSERT INTO yourTable SELECT 5, '2002-01-01', 20, 'Y';
INSERT INTO yourTable SELECT 6, '2000-01-01', 20, 'Y';
INSERT INTO yourTable SELECT 7, '1998-01-01', 20, 'Y';
SELECT
yourTable.*
FROM
(
SELECT
lookup.XYZ,
COALESCE(MAX(yourTable.myDate), lookup.MaxDate) AS MaxDate
FROM
(
SELECT
lookup.XYZ,
COALESCE(MAX(yourTable.myDate), lookup.MaxDate) AS MaxDate
FROM
(
SELECT
yourTable.XYZ,
MAX(yourTable.myDate) AS MaxDate
FROM
yourTable
WHERE
yourTable.ABC = 'Y'
GROUP BY
yourTable.XYZ
)
AS lookup
LEFT JOIN
yourTable
ON yourTable.XYZ = lookup.XYZ
AND yourTable.myDate < lookup.MaxDate
AND yourTable.ABC = 'Y'
GROUP BY
lookup.XYZ,
lookup.MaxDate
)
AS lookup
LEFT JOIN
yourTable
ON yourTable.XYZ = lookup.XYZ
AND yourTable.myDate < lookup.MaxDate
AND yourTable.ABC = 'Y'
GROUP BY
lookup.XYZ,
lookup.MaxDate
)
AS lookup
INNER JOIN
yourTable
ON yourTable.XYZ = lookup.XYZ
AND yourTable.myDate >= lookup.MaxDate
WHERE
yourTable.ABC = 'Y'
ORDER BY
yourTable.comp_id
;
DROP TABLE yourTable;
There are other options, but they're all a bit hacky. Search SO for greatest-n-per-group mysql.
My results using your example data:
Comp_ID | DATE | XYZ | ABC
------------------------------
1 | 2012-1-1 | 10 | Y
2 | 2011-1-1 | 10 | Y
3 | 2006-1-1 | 10 | Y
4 | 2011-1-1 | 20 | Y
5 | 2002-1-1 | 20 | Y
6 | 2000-1-1 | 20 | Y
Here's another way, hopefully more efficient than Dems' answer.
Test it with an index on (abc, xyz, date):
SELECT m.xyz, m.date --- for all columns: SELECT m.*
FROM
( SELECT DISTINCT xyz
FROM money.cash
WHERE abc = 'Y'
) AS dm
JOIN
money.cash AS m
ON m.abc = 'Y'
AND m.xyz = dm.xyz
AND m.date >= COALESCE(
( SELECT im.date
FROM money.cash AS im
WHERE im.abc = 'Y'
AND im.xyz = dm.xyz
ORDER BY im.date DESC
LIMIT 1
OFFSET 2 --- to get 3 latest rows per xyz
), DATE('1000-01-01') ) ;
If you have more than rows with same (abc, xyz, date), the query may return more than 3 rows per xyz (all tied in 3rd place will all be shown).