Union of masked values - sql-server

I've got a problem with making union of 2 tables that have values masked using random function. Unless someone has permission to read all data, user should see random values between (-1000,2000)
making separate views for each table generates the values in a correct way, however there's problem when I try to make union of those 2 tables or views. Instead of seeing random values I see 0 for everything
Let's say there's table A defined as:
ID INT IDENTITY (1, 1) NOT NULL,
Value MONEY MASKED WITH (FUNCTION = 'random(-1000, 20000)') NOT NULL
and table B as:
ID INT IDENTITY (1, 1) NOT NULL,
Value DECIMAL (18, 6) MASKED WITH (FUNCTION = 'random(-1000.000000, 20000.000000)') NULL
in table A:
ID Value
1 12
2 21
3 34
in table B:
ID Value
7 17.12
8 23.01
9 2.56
view on each of table shows ID's of each tables and masked values for user without permissions and values as in table for user with permissions which is correct
however UNION of both tables should show ID's and masked values but instead it shows values = 0.000000.
I'm kinda confused on how to make those values appear as masked random values in union

You can UNION / UNION ALL a select of the same table without problems. But using two different tables gives 0 for all masked values.
You can use the following as a workaround using temporary tables:
SELECT * INTO #t1 FROM TableA
SELECT * INTO #t2 FROM TableB
SELECT * FROM #t1
UNION ALL
SELECT * FROM #t2
demo on dbfiddle.uk

Related

Postgres how to use ANY instead of IN

I have a query but it is not working correctly,
Select *
from "Firms"
Where "Properties" IN ('{1,2}')
That's my postgres query,
"Properties" column is int array.
Only those containing these two values ​​are coming, but I want to fetch records containing any of the values, and I want to list by number of matching values ​​if possible.
Test case:
create table array_any(id integer, array_fld int[]);
insert into array_any values (1, ARRAY[1,2]), (2, ARRAY[2,3]), (3, ARRAY[3,4]);
select id, count(*) from array_any,
lateral unnest(array_fld) as s where s = ANY(ARRAY[1,2]) group by id order by id;
id | count
----+-------
1 | 2
2 | 1

SQL - Normalizing Data returned from Select Statement / Stored Procedure

I am working on building a neural network to do some back-propagation/data analysis.
I am working on normalizing my input data for training purposes.
One of my data sets contains a type identifier, currently there are 8 types(this may change at any time).
In my select statement, I want to have a condition that if TypeId = 1, I actually want to return 00000001. If TypeId = 2, I would like to return 00000011, and repeat. The length of the number would represent the number of Types. The number of ones represents the TypeId.
Any suggestions in how to approach this? I would prefer something a little more dynmaic than what I've provided as the number of types may change.
SELECT TypeId =
CASE TypeId
WHEN 1 THEN 00000001
WHEN 2 THEN 00000011
WHEN 3 THEN 00000111
WHEN 4 THEN 00001111
END,
Name
FROM dbo.Types
DECLARE #t TABLE (TypeId INT, Name VARCHAR(100))
INSERT INTO #t VALUES (1, 'Type1'), (2, 'Type2'), (3, 'Type3'), (10, 'Type10')
SELECT REPLICATE('0', (SELECT MAX(TypeId) FROM #t) - TypeId) + REPLICATE('1', TypeId), Name
FROM #t
Gives:
0000000001 Type1
0000000011 Type2
0000000111 Type3
1111111111 Type10

SQL Update NULL value from select statement query

I'm new to posting on this site, but been using it for a while to get assistance to SQL queries.
I have an issue that I'm trying to resolve. I have 2 columns in a query which are machine and ID, for some machines the ID will be NULL, but for others they will have an ID value as set out below.
Machine ID
test1 3
test12 NULL
test3 4
test4 NULL
As the ID's will be present in the table, I need to update the NULL values, if the machine name is like the one which has a value, for example test 1 and test12 both should have ID 3, but test12 is showing NULL. What I want to be able to do is to replace the NULL for test12 with ID = 3, as the machine names are similar.
I have tried COALESCE, ISNULL and CASE, which all will update the values, but I need know the value, but I wont know it until I have done the select statement.
Any ideas on how to resolve this please?
As noted in the comments you will have to work out your match formula and specify it in the join condition. I believe the query you are looking for is:
Create Table Machines (Name Varchar(8000), ID Int)
Insert Into Machines Values ('test1', 3)
Insert Into Machines Values ('test12', Null)
Insert Into Machines Values ('test3', 4)
Insert Into Machines Values ('test4', Null)
Insert Into Machines Values ('test89', Null)
Insert Into Machines Values ('test8', 5)
Insert Into Machines Values ('test64', Null)
Update M1 Set M1.ID = M2.ID
From Machines M1
Join (Select Left(Name,5) NamePrefix, Max(ID) ID
From Machines
Where ID Is Not Null
Group By Left(Name,5)) M2
On Left(M1.Name, 5) = M2.NamePrefix
Where M1.ID Is Null
Select * From Machines
Note that I used a group by in the joined query in case multiple rows match and we only want one value returned. You can use window functions or other logic instead of the group by if you want to pick specifically which match is chosen.
Based on the requirements in your last comment:
There will be a number of records in the table, they are grouped by the letter before and after the '-' i.e. AB-CDE-L111, AB-CDE-L112, AB-CDE-L113, AB-CDE-L124, AB-CDE-L116 all of these should have in the query an ID of 45. The next set of machines will be AB-CCC-L111, AB-CCC-L112, AB-CCC-L115 all of these should have in the query an ID of 47 and finally there will be the last set of machine, AB-BBB-L113, AB-BBB-L144, AB-BBB-L115, AB-BBB-L120 all of these should have in the query an ID of 50. In the query, a machine returns a NULL ID then I need to update the query results, not the table.
So a SELECT query to get you your results would be:
declare #machine table (Machine varchar(30) not null, ID int null)
insert into #machine
values ('AB-CDE-L111', NULL),
('AB-CDE-L112', NULL),
('AB-CDE-L113', 45),
('AB-CDE-L124', NULL),
('AB-CDE-L116', NULL),
('AB-CCC-L111', NULL),
('AB-CCC-L112', NULL),
('AB-CCC-L113', 47),
('AB-CCC-L124', NULL),
('AB-CCC-L116', NULL),
('AB-BBB-L111', NULL),
('AB-BBB-L112', NULL),
('AB-BBB-L113', 50),
('AB-BBB-L124', NULL),
('AB-BBB-L116', NULL)
select m1.Machine, m2.ID
from #machine m1
inner join #machine m2
on m2.ID is not null
and left(m2.Machine, 6) = left(m1.Machine, 6)
order by m1.Machine
This assumes that:
1) There is always the same amount of characters making up the prefix to the machine code.
2) That there is only one Machine in each group that has been assigned an ID.
If either of these assumptions is wrong then you may need to do extra string manipulation in the case of 1) and use some kind of function (ROW_NUMBER etc.) in the case of 2) to avoid duplicate rows (although you could just use SELECT DISTINCT if the IDs would be the same).

conditional "next value for sequence"

scenario:
Sql Server 2012 Table named "Test" has two fields. "CounterNo" and "Value" both integers.
There are 4 sequence objects defined named sq1, sq2, sq3, sq4
I want to do these on inserts:
if CounterNo = 1 then Value = next value for sq1
if CounterNo = 2 then Value = next value for sq2
if CounterNo = 3 then Value = next value for sq3
I think, create a custom function assign it as default value of Value field. But when i tried custom functions not supports "next value for Sequence Objects"
Another way is using trigger. That table has trigger already.
Using a Stored Procedure for Inserts is the best way. But EntityFramework 5 Code-First is not supporting it.
Can you suggest me a way to achieve this.
(if you show me how can i do it with custom functions you can also post it here. It's another question of me.)
Update:
In reality there are 23 fields in that table and also primary keys setted and i'm generating this counter value on software side, using "counter table".It is not good to generate counter values on client side.
I'm using 4 sequence objects as counters because they represents different types of records.
If i use 4 counters on same record at same time, all of them generates next values. I want only related counter generates it's next value while others remains same.
I'm not shure if I fully understand your use case but maybe the following sample illustrates what you need.
Create Table Vouchers (
Id uniqueidentifier Not Null Default NewId()
, Discriminator varchar(100) Not Null
, VoucherNumber int Null
-- ...
, MoreData nvarchar(100) Null
);
go
Create Sequence InvoiceSequence AS int Start With 1 Increment By 1;
Create Sequence OrderSequence AS int Start With 1 Increment By 1;
go
Create Trigger TR_Voucher_Insert_VoucherNumer On Vouchers After Insert As
If Exists (Select 1 From inserted Where Discriminator = 'Invoice')
Update v
Set VoucherNumber = Next Value For InvoiceSequence
From Vouchers v Inner Join inserted i On (v.Id = i.Id)
Where i.Discriminator = 'Invoice';
If Exists (Select 1 From inserted Where Discriminator = 'Order')
Update v
Set VoucherNumber = Next Value For OrderSequence
From Vouchers v Inner Join inserted i On (v.Id = i.Id)
Where i.Discriminator = 'Order';
go
Insert Into Vouchers (Discriminator, MoreData)
Values ('Invoice', 'Much')
, ('Invoice', 'More')
, ('Order', 'Data')
, ('Invoice', 'And')
, ('Order', 'Again')
;
go
Select * From Vouchers;
Now Invoice- and Order-Numbers will be incremented independently. And as you can have multiple insert triggers on the same table, that shouldn't be an issue.
I think you're thinking about this in the wrong way. You have 3 values and these values are determined by another column. Switch it around, create 3 columns and remove the Counter column.
If you have a table with value1, value2 and value3 then the Counter value is implied by the column in which the value resides. Create a unique index on these three columns and add an identity column for a primary key and you're sorted; you can do it all in a stored procedure easily.
If you have four different types of records, use four different tables, with a separate identity column in each one.
If you need to see all the data together, then use a view to combine them:
create v_AllTypes as
select * from type1 union all
select * from type2 union all
select * from type3 union all
select * from type4;
Alternatively, do the calculation of the sequence number on output:
select t.*,
row_number() over (partition by CounterNo order by t.id) as TypeSeqNum
from AllTypes t;
Something seems amiss with your data model if it requires conditional updates to four identity columns.

Maintain ordering of characters if there is no id (SQL Server 2005)

I have the following
Chars
A
C
W
B
J
M
How can I insert some sequential numbers so that after insertion of the numbers the order of characters will not change?
I mean if I use row_number(), the output Character order is changing like
select
ROW_NUMBER() over(order by chars) as id,
t.* from #t t
Output:
id chars
1 A
2 B
3 C
4 J
5 M
6 W
My desired expectation is
id chars
1 A
2 C
3 W
4 B
5 J
6 M
Also, I cannot use any identity field like id int identity because I am in the middle of a query and I need to maintain a inner join for achieving something.
I hope I do make myself clear.
Please help.
Thanks in advance
There is no implicit ordering of rows in SQL. If some ordering is desired, be it order in which items were inserted or any other order, it must be supported by a user-defined column.
In other words, the SQL standard doesn't require the SQL implementations to maintain any order. On the other hand the ORDER BY clause in a SELECT statement can be used to specify the desired order, but such ordering is supported by the values in a particular (again, user defined) column.
This user defined column may well be an auto-incremented column for which SQL assigns incremental (or otherwise) values to, and this may be what you need.
Maybe something like...
CREATE TABLE myTable
(
InsertID smallint IDENTITY(1,1),
OneChar CHAR(1),
SomeOtherField VARCHAR(20)
-- ... etc.
)
INSERT INTO myTable (OneChar, SomeOtherField) VALUES ('A', 'Alpha')
INSERT INTO myTable (OneChar, SomeOtherField) VALUES ('W', 'Whiskey')
INSERT INTO myTable (OneChar, SomeOtherField) VALUES ('B', 'Bravo')
-- ... etc.
SELECT OneChar
FROM myTable
ORDER BY InsertId
'A'
'W'
'B'
--...

Resources