Find row with the most true value columns - sql

Table User
estado_id
user_id
shopping
mercado
feira
1
1
1
0
1
1
2
1
1
1
1
3
1
0
1
Table Cidade
estado_id
version_id
name
type
1
1
jose
shopping
1
2
maria
feira
1
2
maria
mercado
1
3
bruna
mercado
I need to compare the states, and bring only those that cover user x criteria's, but the user table may contain hundreds of users and I just have to return to which user x is bound. In the users table, I need to bring everyone that they think matches. If in the shopping and fair table the value is 1 and market to 0 then shopping and fair must be returned within these versions, I managed to bring up only the user data / id_state, however when I compare the user table = 1 with the city table type = shopping
But I cannot find a way to do that, because' it needs to be dynamic
WITH CTE AS (
SELECT cidade.*, uv.user_id, uv.shopping, uv.mercado, uv.feira
FROM cidade
INNER JOIN userst as uv ON cidade.estado_id = uv.estado_id
WHERE cidade.estado_id = 1 AND uv.user_id = 1
)
SELECT [type], shopping, mercado, feira
FROM CTE
My expectation
estado_id
version_id
name
type
user_id
1
1
jose
shopping
1
CREATE TABLE cidade(
estado_id int,
version_id int,
name varchar(255),
[type] varchar(255)
);
CREATE TABLE userst (
estado_id int,
user_id int,
shopping int,
mercado int,
feira int
);
INSERT INTO cidade (estado_id, version_id, name, [type])
VALUES (1, 1, 'jose', 'shopping')
, (1, 2, 'maria', 'feira')
, (1, 2, 'maria', 'mercado')
, (1, 3, 'bruna', 'mercado');
INSERT INTO userst (estado_id, user_id, shopping, mercado, feira)
VALUES (1, 1, 1, 0, 1)
, (1, 2, 1, 1, 1)
, (1, 3, 1, 0, 1);

Related

Choose a record from the table where two of the default values are 0 or 1, a bit tricky

Looking for a more elegant and most logical solution for:
The table:
index
id
by_default
text
1
1
0
AAA
2
1
1
ABA
3
1
0
ABC
4
2
0
BCA
5
2
0
BCB
The task is to find the minimum index value with defaults set to 1 and/or defaults set to 0.
I have the following code (not very elegant, but it works, also very slow):
declare #byd_1 as int=
(select min(t.index) idx from Table t where t.[id]=1 and t.by_default=1)
declare #byd_2 as int=
(select min(t.index) idx from Table t where t.[id]=1 and t.by_default=0)
select (case when #byd_1 is null then #byd_2 else #byd_1 end)
The tricky part is: sometimes the by_default column is always 0 (for example: id:2 may have no by_default values set) and as mentioned earlier the task is: need to get the minimum value of the index column.
What is the most elegant (one-line) code possible?
Using MSSQL
The expected results, according to the sample table, should be the following:
index
id
by_default
text
2
1
1
ABA
4
2
0
BCA
Edited to add text also.
A bit ugly but:
drop table #t
select *
into #t
from (
VALUES (1, 1, 0, N'AAA')
, (2, 1, 1, N'ABA')
, (3, 1, 0, N'ABC')
, (4, 2, 0, N'BCA')
, (5, 2, 0, N'BCB')
) t (index_,id,by_default,text)
select index_, id, by_default, text
from (
select min(index_) OVER(PARTITION BY id) AS minIndex
, MIN(case when by_default = 1 then index_ end) over(partition by id) AS minIndexDefault
, *
from #t
) t
where isnull(minIndexDefault, minIndex) = index_

Automatically set SUM calculation's result as column value during / after row insert

I have an SQL table called "credits" which contain the following columns:
id (Serial ID for rows (1,2,3,....))
account_id (ID of associated client)
change (int4)
rolling_change
Every time during/after a row insert, I'd like the result of this Query to be the "rolling_change" column's value:
SELECT SUM(change)
FROM credits
WHERE account_id = {account_id} AND id < {this_id};
How can I make this process happen automatically on every row insert?
(I'm using DBeaver for reference)
Here's an example that updates the empty rolling_change after inserts.
CREATE TABLE credits (
id SERIAL PRIMARY KEY,
account_id INT NOT NULL,
change INT NOT NULL,
rolling_change INT
);
CREATE OR REPLACE FUNCTION calc_credits_rolling_change()
RETURNS trigger AS $calc_rolling_change$
BEGIN
UPDATE credits tgt
SET rolling_change = src.rolling_change
FROM (
SELECT id
, SUM(change) OVER (PARTITION BY account_id
ORDER BY id) AS rolling_change
FROM credits
) src
WHERE src.id = tgt.id
AND tgt.rolling_change IS NULL;
RETURN NEW;
END;
$calc_rolling_change$ LANGUAGE plpgsql;
CREATE TRIGGER trg_credits_rolling_change
AFTER INSERT
ON credits
EXECUTE PROCEDURE calc_credits_rolling_change();
INSERT INTO credits (account_id, change) VALUES
(1, 1), (1, 0)
, (2, 1), (2, 1), (2, 0);
INSERT INTO credits (account_id, change) VALUES
(3, 2), (3, 1), (1, 10)
select * from credits order by account_id, id;
id
account_id
change
rolling_change
1
1
1
1
2
1
0
1
8
1
10
11
3
2
1
1
4
2
1
2
5
2
0
2
6
3
2
2
7
3
1
3
Demo on db<>fiddle here

Write a function or regular expression that will split string in sql

i have in sql table values in this way:
Id GameId GameSupplierId
1 1 NULL
2 2 NULL
3 3 1
4 3 2
5 3 3
What i want is to filter in sql procedure by GameId and if there is GameSupplierId by supplier too. I will get string from my web page in format GameID ; GameSupplierId. For example:
1; NULL
2; NULL
or if there is GameSupplier too
3;1
3;1,2
Also i want to have multiple choice for example like this:
1,2,3;1,2
In my sql query i will then filter like WHERE #GameID = Table.GameID (and also to check #GameSupplierId IN (,,,))
Just add your desired columns into ORDER BY:
ORDER BY t.GameId, t.GameSuplierId
For example:
DECLARE #table TABLE
(
ID INT,
GameId INT,
GameSuplierId INT NULL
)
INSERT INTO #table
(
ID,
GameId,
GameSuplierId
)
VALUES
(1, 1, NULL)
, (2, 2, NULL)
, (3, 3, 1)
, (4, 3, 2)
, (5, 3, 3)
SELECT
*
FROM #table t
ORDER BY t.GameId, t.GameSuplierId

Change column type in table

I have a datatable called deal in Oracle with four columns:
DealID: (PK)
LegID
OrigID
Description
The problem is that if I want to insert a deal with description = A, the attributes LegID and OrigID must be unique, otherwise, there is not problem. How can i make this check? I had thought a trigger after insert. There are more solutions?
Thanks in advance!!
You need a function based unique index :
create table tt (
DealID number(10) primary key,
LegID number(10),
OrigID number(10),
Description varchar2(200 char)
);
create unique index tt_leg_orig_dscr_uk on tt (
case when description = 'A' then description end,
case when description = 'A' then legid end,
case when description = 'A' then origid end
);
insert into tt values (1, 1, 1, 'A');
1 row(s) inserted.
insert into tt values (2, 1, 1, 'A');
ORA-00001: unique constraint (XXXXX.TT_LEG_ORIG_DSCR_UK) violated
insert into tt values (2, 1, 2, 'A');
1 row(s) inserted.
select * from tt;
DEALID LEGID ORIGID DESCRIPTION
-----------------------------------
1 1 1 A
2 1 2 A
2 rows returned in 0.01 seconds
insert into tt values (3, 1, 1, 'B');
1 row(s) inserted.
insert into tt values (4, 1, 1, 'B');
1 row(s) inserted.
select * from tt order by 1;
DEALID LEGID ORIGID DESCRIPTION
-----------------------------------
1 1 1 A
2 1 2 A
3 1 1 B
4 1 1 B
4 rows returned in 0.01 seconds
As you can see, the unique index work only with records with description = 'A', It allows to have non-unique records for different descriptions.

TSQL - Help with UNPIVOT

I am transforming data from this legacy table:
Phones(ID int, PhoneNumber, IsCell bit, IsDeskPhone bit, IsPager bit, IsFax bit)
These bit fields are not nullables and, potentially, all four bit fields can be 1.
How can I unpivot this thing so that I end up with a separate row for each bit field = 1. For instance, if the original table looks like this...
ID, PhoneNumber, IsCell, IsPager, IsDeskPhone, IsFax
----------------------------------------------------
1 123-4567 1 1 0 0
2 123-6567 0 0 1 0
3 123-7567 0 0 0 1
4 123-8567 0 0 1 0
... I want the result to be the following:
ID PhoneNumber Type
-----------------------
1 123-4567 Cell
1 123-4567 Pager
2 123-6567 Desk
3 123-7567 Fax
4 123-8567 Desk
Thanks!
2005/2008 version
SELECT ID, PhoneNumber, Type
FROM
(SELECT ID, PhoneNumber,IsCell, IsPager, IsDeskPhone, IsFax
FROM Phones) t
UNPIVOT
( quantity FOR Type IN
(IsCell, IsPager, IsDeskPhone, IsFax)
) AS u
where quantity = 1
see also Column To Row (UNPIVOT)
Try this:
DROP TABLE #Phones
CREATE TABLE #Phones
(
Id int,
PhoneNumber varchar(50),
IsCell bit,
IsPager bit,
IsDeskPhone bit,
IsFax bit
)
INSERT INTO #Phones VALUES (1, '123-4567', 1, 1, 0, 0)
INSERT INTO #Phones VALUES (2, '123-6567', 0, 0, 1, 0)
INSERT INTO #Phones VALUES (3, '123-7567', 0, 0, 0, 1)
INSERT INTO #Phones VALUES (4, '123-8567', 0, 0, 1, 0)
SELECT Id, PhoneNumber, [Type]
FROM (
SELECT Id, PhoneNumber,
Cell = IsCell, Pager = IsPager,
Desk = IsDeskPhone, Fax = IsFax
FROM #Phones
) a
UNPIVOT(
something FOR [Type] IN (Cell, Pager, Desk, Fax )
) as upvt