I'm trying to make a SQL query where I can find all ids of a member (member_ids) with all branches.
This all branches is an array consisting of all branch ids. So for example the values of all branches is [1,2,3,4,5,6,7,8,9,10].
I want to query similar to this one:
SELECT member_id FROM member_branch WHERE branch_id IN [1,2,3,4,5,6,7,8,9,10]
But to query all member_id having all branch_id. Because if a member_id has only [1,2,3], it will be included also in the query, and I don't want.
Try this,
SELECT member_id FROM member_branch where branch_id IN (1,2,3,4);
Will this not work.
declare #branchCount int =10
select member_id from (SELECT member_id, branch_id FROM member_branch WHERE branch_id IN ('1','2','3','4','5','6','7','8','9','10')) a group by a.member_id having count(a.member_id)>=#branchCount
If I understand the question correctly and based on the format of the data in the branch_id column ( which is a valid JSON array), you may try to use a JSON-based approach. When you parse a JSON array ([1,2,3,4,5,6,7,8,9,10] for example) using OPENJSON() and default schema, the result is a table with columns key, value and type. After that, you may use any set-base approach (EXCEPT and OUTER APPLY in the example).
Table:
CREATE TABLE member_branch (
member_id int,
branch_id nvarchar(100)
)
INSERT INTO member_branch
(member_id, branch_id)
VALUES
(1, '[1,2,3,4,5,6,7,8,9,10]'),
(2, '[1,2,3,4]'),
(3, '[10]'),
(4, '[1,2,3,4,5,6,7,8,9,10]')
DECLARE #branches nvarchar(100) = N'[1,2,3,4,5,6,7,8,9,10]'
Statement:
SELECT m.member_id
FROM member_branch m
OUTER APPLY (
SELECT [value] FROM OPENJSON(#branches)
EXCEPT
SELECT [value] FROM OPENJSON(m.branch_id)
) j
WHERE j.[value] IS NULL
Result:
---------
member_id
---------
1
4
Related
Lets say I have som data that looks like
create table test.from
(
id integer primary key,
data json
);
insert into test.from
values
(4, '{ "some_field": 11 }'),
(9, '{ "some_field": 22 }');
create table test.to
(
id integer primary key,
some_field int
);
I would like the rows in the "to" table to have the same id key as the "from" row, and expand the json into separate columns. But using json_populate_record like below, will unsurprisingly give me null as key.
Method 1:
insert into test.to
select l.*
from test.from fr
cross join lateral json_populate_record(null::test.to, fr.data) l;
I can achieve what I'm looking for by naming columns like below
Method 2:
insert into test.to (id, some_field)
select
fr.id as id,
l.some_field
from test.from fr
cross join lateral json_populate_record(null::test.to, fr.data) l;
The challenge is that I want to avoid naming any columns other than the id column, both since it gets tedious, but also since I'd like to do this in a function where the column names are not known.
What modifications do I have to do to Method 1 to update the record with the correct id?
Just append the id key to your data like this:
insert into test.to
select l.*
from
test.from fr
cross join lateral jsonb_populate_record(
null::test.to,
fr.data::jsonb || jsonb_build_object('id', fr.id)) l;
I will create table where I will insert multiple values for different companies. Basically I have all values that are in the table below but I want to add a column IndicatorID which is linked to IndicatorName so that every indicator has a unique id. This will obviously not be a PrimaryKey.
I will insert the data with multiple selects:
CREATE TABLE abc
INSERT INTO abc
SELECT company_id, 'roe', roevalue, metricdate
FROM TABLE1
INSERT INTO abc
SELECT company_id, 'd/e', devalue, metricdate
FROM TABLE1
So, I don't know how to add the IndicatorID I mentioned above.
EDIT:
Here is how I populate my new table:
INSERT INTO table(IndicatorID, Indicator, Company, Value, Date)
SELECT [the ID that I need], 'NI_3y' as 'Indicator', t.Company, avg(t.ni) over (partition by t.Company order by t.reportdate rows between 2 preceding and current row) as 'ni_3y',
t.reportdate
FROM table t
LEFT JOIN IndicatorIDs i
ON i.Indicator = roe3 -- the part that is not working if I have separate indicatorID table
I am going to insert different indicators for the same companies. And I want indicatorID.
Your "indicator" is a proper entity in its own right. Create a table with all indicators:
create table indicators (
indicator_id int identity(1, 1) primary key,
indicator varchar(255)
);
Then, use the id only in this table. You can look up the value in the reference table.
Your inserts are then a little more complicated:
INSERT INTO indicators (indicator)
SELECT DISTINCT roevalue
FROM table1 t1
WHERE NOT EXISTS (SELECT 1 FROM indicators i2 WHERE i2.indicator = t1.roevalue);
Then:
INSERT INTO ABC (indicatorId, companyid, value, date)
SELECT i.indicatorId, t1.company, v.value, t1.metricdate
FROM table1 t1 CROSS APPLY
(VALUES ('roe', t1.roevalue), ('d/e', t1.devalue)
) v(indicator, value) JOIN
indicators i
ON i.indicator = v.indicator;
This process is called normalization and it is the typical way to store data in a database.
DDL and INSERT statement to create an indicators table with a unique constraint on indicator. Because the ind_id is intended to be a foreign key in the abc table it's created as a non-decomposable surrogate integer primary key using the IDENTITY property.
drop table if exists test_indicators;
go
create table test_indicators (
ind_id int identity(1, 1) primary key not null,
indicator varchar(20) unique not null);
go
insert into test_indicators(indicator) values
('NI'),
('ROE'),
('D/E');
The abc table depends on the ind_id column from indicators table as a foreign key reference. To populate the abc table company_id's are associated with ind_id's.
drop table if exists test_abc
go
create table test_abc(
a_id int identity(1, 1) primary key not null,
ind_id int not null references test_indicators(ind_id),
company_id int not null,
val varchar(20) null);
go
insert into test_abc(ind_id, company_id)
select ind_id, 102 from test_indicators where indicator='NI'
union all
select ind_id, 103 from test_indicators where indicator='ROE'
union all
select ind_id, 104 from test_indicators where indicator='D/E'
union all
select ind_id, 103 from test_indicators where indicator='NI'
union all
select ind_id, 105 from test_indicators where indicator='ROE'
union all
select ind_id, 102 from test_indicators where indicator='NI';
Query to get result
select i.ind_id, a.company_id, i.indicator, a.val
from test_abc a
join test_indicators i on a.ind_id=i.ind_id;
Output
ind_id company_id indicator val
1 102 NI NULL
2 103 ROE NULL
3 104 D/E NULL
1 103 NI NULL
2 105 ROE NULL
1 102 NI NULL
I was finally able to find the solution for my problem which seems to me very simple, although it took time and asking different people about it.
First I create my indicators table where I assign primary key for all indicators I have:
CREATE TABLE indicators (
indicator_id int identity(1, 1) primary key,
indicator varchar(255)
);
Then I populate easy without using any JOINs or CROSS APPLY. I don't know if this is optimal but it seems as the simplest choice:
INSERT INTO table(IndicatorID, Indicator, Company, Value, Date)
SELECT
(SELECT indicator_id from indicators i where i.indicator = 'NI_3y) as IndicatorID,
'NI_3y' as 'Indicator',
Company,
avg(ni) over (partition by Company order by reportdate rows between 2 preceding and current row) as ni_3y,
reportdate
FROM TABLE1
I am working to select data from 2 different table but I can't figured out. If I use INNER JOIN it show noting. Any help are welcome and Thanks.
My First table:
CREATE TABLE P_N(
PN_ID int NOT NULL,
PN VARCHAR (1000),
primary key (PN_ID)
);
My second Table:
CREATE TABLE NAME (
NAME_ID VARCHAR(60) PRIMARY key,
NAME VARCHAR (40)
);
My select code :
SELECT DISTINCT NAME.NAME_ID, PN.PN_ID
FROM NAME
FULL JOIN P_N
ON PN.PN =NAME.NAME_ID;
If I use left or full Join this is the result:
NAME_ID PN_ID
nm0006300 NULL
nm0006400 NULL
nm0006500 NULL
nm0006600 NULL
nm0006700 NULL
AND if I use right join:
NAME_ID PN_ID
null 921691
null 921692
null 921693
null 921694
This is what I want the result to looks like For example:
NAME_ID PN_ID
nm0006300 921691
nm0006400 921692
nm0006500 921693
nm0006600 921694
You don't seem to have a JOIN key. You can add one with ROW_NUMBER():
SELECT n.NAME_ID, PN.PN_ID
FROM (SELECT n.*, ROW_NUMBER() OVER (ORDER BY NAME_ID) as seqnum
FROM NAME n
) n JOIN
(SELECT pn.*, ROW_NUMBER() OVER (ORDER BY PN) as seqnum
FROM P_N pn
) pn
ON PN.seqnum = n.seqnum;
try this
select DISTINCT NAME.NAME_ID, PN.PN_ID
from NAME,P_N as PN
where PN.PN =NAME.NAME_ID
I'm stuck with this since last week. I have two tables, where the id column of CustomerTbl correlates with CustomerID column of PurchaseTbl:
What I'm trying to achieve is I want to duplicate the data of the table from itself, but copy the newly generated id of CustomerTbl to PurchaseTbl's CustomerID
Just like from the screenshots above. Glad for any help :)
You may use OUTPUT clause to access to the new ID. But to access to both OLD ID and NEW ID, you will need to use MERGE statement. INSERT statement does not allow you to access to the source old id.
first you need somewhere to store the old and new id, a mapping table. You may use table variable or temp table
declare #out table
(
old_id int,
new_id int
)
then the merge statement with output clause
merge
#CustomerTbl as t
using
(
select id, name
from CustomerTbl
) as s
on 1 = 2 -- force it to `false`, not matched
when not matched then
insert (name)
values (name)
output -- the output clause
s.id, -- old_id
inserted.id -- new_id
into #out (old_id, new_id);
after that you just use the #out to join back using old_id to obtain the new_id for the PurchaseTbl
insert into PurchaseTbl (CustomerID, Item, Price)
select o.new_id, p.Item, p.Price
from #out o
inner join PurchaseTbl p on o.old_id = p.CustomerID
Not sure what your end game is, but one way you could solve this is this:
INSERT INTO purchaseTbl ( customerid ,
item ,
price )
SELECT customerid + 3 ,
item ,
price
FROM purchaseTbl;
I'm working with SQL Server 2012 and wish to query the following:
I've got 2 tables with mostly different columns. (1 table has 10 columns the other has 6 columns).
however they both contains a column with ID number and another column of category_name.
The ID numbers may be overlap between the tables (e.g. 1 table may have 200 distinct IDs and the other 900 but only 120 of the IDs are in both).
The Category name are different and unique for each table.
Now I wish to have a single table that will include all the rows of both tables, with a single ID column and a single Category_name column (total of 14 columns).
So in case the same ID has 3 records in table 1 and another 5 records in table 2 I wish to have all 8 records (8 rows)
The complex thing here I believe is to have a single "Category_name" column.
I tried the following but when there is no null in both of the tables I'm getting only one record instead of both:
SELECT isnull(t1.id, t2.id) AS [id]
,isnull(t1.[category], t2.[category_name]) AS [category name]
FROM t1
FULL JOIN t2
ON t1.id = t2.id;
Any suggestions on the correct way to have it done?
Make your FULL JOIN ON 1=0
This will prevent rows from combining and ensure that you always get 1 copy of each row from each table.
Further explanation:
A FULL JOIN gets rows from both tables, whether they have a match or not, but when they do match, it combines them on one row.
You wanted a full join where you never combine the rows, because you wanted every row in both tables to appear one time, no matter what. 1 can never equal 0, so doing a FULL JOIN on 1=0 will give you a full join where none of the rows match each other.
And of course you're already doing the ISNULL to make sure the ID and Name columns always have a value.
SELECT ID, Category_name, (then the other 8 columns), NULL, NULL, NULL, NULL
FROM t1
UNION ALL
SELECT ID, Category_name, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (then the other 4 columns)
FROM t2
This demonstrates how you can use a UNION ALL to combine the row sets from two tables, TableA and TableB, and insert the set into TableC.
Create two source tables with some data:
CREATE TABLE dbo.TableA
(
id int NOT NULL,
category_name nvarchar(50) NOT NULL,
other_a nvarchar(20) NOT NULL
);
CREATE TABLE dbo.TableB
(
id int NOT NULL,
category_name nvarchar(50) NOT NULL,
other_b nvarchar(20) NOT NULL
);
INSERT INTO dbo.TableA (id, category_name, other_a)
VALUES (1, N'Alpha', N'ppp'),
(2, N'Bravo', N'qqq'),
(3, N'Charlie', N'rrr');
INSERT INTO dbo.TableB (id, category_name, other_b)
VALUES (4, N'Delta', N'sss'),
(5, N'Echo', N'ttt'),
(6, N'Foxtrot', N'uuu');
Create TableC to receive the result set. Note that columns other_a and other_b allow null values.
CREATE TABLE dbo.TableC
(
id int NOT NULL,
category_name nvarchar(50) NOT NULL,
other_a nvarchar(20) NULL,
other_b nvarchar(20) NULL
);
Insert the combined set of rows into TableC:
INSERT INTO dbo.TableC (id, category_name, other_a, other_b)
SELECT id, category_name, other_a, NULL AS 'other_b'
FROM dbo.TableA
UNION ALL
SELECT id, category_name, NULL, other_b
FROM dbo.TableB;
Display the results:
SELECT *
FROM dbo.TableC;