DAX: Returning information on two (or more) matching items in a single column - filtering

in PowerPivot, I am struggling to find information on matching values in the same column.
I would like to display the matching name in the below table, e.g. for John with ID '1' it would be Peter (also with ID '1'), for Jack (ID '2') it would be Mary (also ID '2'), etc.
I have been able to 1) find the number of occurrences using:
=COUNTX(FILTER (Table2, (EARLIER ( [ID] ) = [ID] )),Table2[Name])
...also, I was able to add up the matching values with
=SUMX(FILTER (Table2, (EARLIER ( [ID] ) = [ID] )),Table2[Name])
...but was unable to display 'Peter' in the row of 'John' and 'John' in the row of Peter.
I am assuming it is possible, not sure how...any help would be much appreciated!

OK, I found a solution (thanks to TomMartens on the Power BI blog), it is CONCATENATEX, working exactly the same as SUMX or COUNTX).
Thanks everyone!

Related

multiple form fields with the same path inserting to db in spring

I have to insert data to db in form fields that have the same path and i want to save it different id's but rather it concatenated it with ",", how could i possibly do it?
I tried to make some alias in SQL but it saves into same db field name with concatenated with ","
i expected in db when i insert that
EX.
db field name = description
input 1 value = "john";
input 2 value = "doe";
id description
1 john
2 doe
above is my expected result
but in my case when i insert it shows these
id description
1 john,doe
can someone help me to achieve that result ? THANKYOU!
Let me present a similar situation. You have a database of people and you are concerned that each person might have multiple phone numbers.
CREATE TABLE Persons (
person_id INT UNSIGNED AUTO_INCREMENT,
...
PRIMARY KEY(person_id) );
CREATE TABLE PhoneNumbers (
person_id INT UNSIGNED,
phone VARCHAR(20) CHARACTER SET ascii,
type ENUM('unknown', 'cell', 'home', 'work'),
PRIMARY KEY(person_id, phone) );
The table PhoneNumbers has a "many-to-1" relationship between phone numbers and persons. (It does not care if two persons share the same number.)
SELECT ...
GROUP CONCAT(pn.phone) AS phone_numbers,
...
FROM Persons AS p
LEFT JOIN PhoneNumbers AS pn USING(person_id)
...;
will deliver a commalist of phone numbers (eg: 123-456-7890,333-444-5555) for each person being selected. Because of the LEFT, it will deliver NULL in case a person has no associated phones.
To address your other question: It is not practical to split a commalist into the components.

TSQL - Parsing substring out of larger string

I have a bunch of rows with values that look like below. It's json extract that I unfortunately have to parse out and load. Anyway, my json parsing tool for some reason doesn't want to parse this full column out so i need to do it in TSQL. I only need the unique_id field:
[{"unique_id":"12345","system_type":"Test System."}]
I tried the below SQL but it's only returning the first 5 characters of the whole column. I know what the issue is which is I need to know how to tell the substring to continue until the 4th set of quotes which comes after the value. I'm not sure how to code the substring like that.
select substring([jsonfield],CHARINDEX('[{"unique_id":"',[jsonfield]),
CHARINDEX('"',[jsonfield]) - CHARINDEX('[{"unique_id":"',[jsonfield]) +
LEN('"')) from etl.my_test_table
Can anyone help me with this?
Thank you, I appreciate it!
Since you tagged 2016, why not use OPENJSON()
Here's an example:
DECLARE #TestData TABLE
(
[SampleData] NVARCHAR(MAX)
);
INSERT INTO #TestData (
[SampleData]
)
VALUES ( N'[{"unique_id":"12345","system_type":"Test System."}]' )
,( N'[{"unique_id":"1234567","system_type":"Test System."},{"unique_id":"1234567_2","system_type":"Test System."}]' )
SELECT b.[unique_id]
FROM #TestData [a]
CROSS APPLY
OPENJSON([a].[SampleData], '$')
WITH (
[unique_id] NVARCHAR(100) '$.unique_id'
) AS [b];
Giving you:
unique_id
---------------
12345
1234567
1234567_2
You can get all the fields as well, just add them to the WITH clause:
SELECT [b].[unique_id]
, [b].[system_type]
FROM #TestData [a]
CROSS APPLY
OPENJSON([a].[SampleData], '$')
WITH (
[unique_id] NVARCHAR(100) '$.unique_id'
, [system_type] NVARCHAR(100) '$.system_type'
) AS [b];
Take it step by step
First get everything to the left of system_type
SELECT LEFT(jsonfield, CHARINDEX('","system_type":"',jsonfield) as s
FROM -- etc
Then take everything to the right of "unique_id":"
SELECT RIGHT(S, LEN(S) - (CHARINDEX('"unique_id":"',S) + 12)) as Result
FROM (
SELECT LEFT(jsonfield, CHARINDEX('","system_type":"',jsonfield) as s
FROM -- etc
) X
Note, I did not test this so it could be off by one or have a syntax error, but you get the idea.
If your larger string ist just a simple JSON as posted, the solution is very easy:
SELECT
JSON_VALUE(N'[{"unique_id":"12345","system_type":"Test System."}]','$[0].unique_id');
JSON_VALUE() needs SQL-Server 2016 and will extract one single value from a specified path.

Comparing Array fields for Nulls,Equal,Not equal - Postgres

Table Name: customers
customer_id Profiles dept_code
------------------------------------------
3361 ,15,31,4, ,01,02,
3362 ,32, ,01,03,
3363 ,04,
3364 ,1,20,21, ,01,02,03,
Table Name :customers_backup
customer_id Profiles dept_code
--------------------------------------
3361 ,15,31,4, ,01,02,
3362 ,32,33,34, ,01,03,
3363 ,10, ,04,
3364 ,1,20,21, ,01,02,03,
I am trying to update the PROFILE of CUSTOMERS table and the conditions are given below,
1) If customer profile is NULL => update customers_backup profile
2) If customer profile equal to customers_backup profile => just keep customer
profile
3) If customers profile <> to customers_backup profile => Keep customer profile and append the profile from customers_backup that is not in the customers table.
I need the following output :
Table Name: customers
customer_id Profiles dept_code
------------------------------------------------
3361 ,15,31,4, ,01,02,
3362 ,32,33,34, ,01,03, ( How to apply this condition?)
3363 ,10, ,04,
3364 ,1,20,21, ,01,02,03,
Below is what I wrote for condition 1 & 2. But they don't give the expected result.
update customers set profiles=
CASE WHEN (select unnest(array[customers.profiles])) is null
THEN customers_backup.profiles
WHEN (select unnest(array[customers.profiles])) =
(select unnest(array[customers_backup.profiles]))
THEN customers.profiles
WHEN (select unnest(array[customers.profiles])) <>
(select unnest(array[customers_backup.profiles])) --- Need help here
THEN user_enrollment_backup1.profiles
END FROM customers_backup
WHERE customers_backup.customer_id=customers.customer_id
AND customers_backup.dept_code= customers.dept_code;
Can someone help? Thanks in advance.
If you want to use actual arrays, you need to clean up your data first so it's in the correct format -- i.e. no leading/trailing commas. Once you have this, you can CAST your profiles field as an array data type and use array concatenation, similar to this:
SELECT
ARRAY(SELECT DISTINCT UNNEST(customers.profiles || customers_backup.profiles))
FROM ...
This should combine your array elements into one array, then unnest & remove duplicate elements, and then finally combine back into the final array. I don't think they will be ordered, but this should get you started.
It looks like your profile values are not real arrays, so you'd need to CAST them as arrays in the query above.
You may use an UPDATE table FROM syntax.
Note that arrays can be compared using = and <> operators.
Only for finding the union (3rd case ), you could use UNNEST.
UPDATE customers AS c
SET profiles = CASE WHEN c.profiles IS NULL
THEN cb.profiles
WHEN array[c.profiles] = array[cb.profiles]
THEN c.profiles
WHEN array[c.profiles] <> array[cb.profiles]
THEN ( select string_agg(a,'')
from (
select distinct
unnest(array[RTRIM(c.profiles,',')::VARCHAR] || array[cb.profiles]) as a
) s
)
END
FROM customers_backup as cb
WHERE c.customer_id = cb.customer_id;
Also note that If you create extension intarray, you may use simple | operator for array UNIONs.
DEMO

T-SQL - compare column values and column names

I am trying to get the values from a small table, that are not present as columns in an existing table.
Here is some code I tried in SQL Server 2012:
BEGIN TRAN;
GO
CREATE TABLE [dbo].[TestValues](
[IdValue] [int] IDENTITY(1,1) NOT NULL,
[Code] [nvarchar](100) NULL,
) ON [PRIMARY];
GO
CREATE TABLE [dbo].[TestColumns](
[DateHour] [datetime2](7) NULL,
[test1] [nvarchar](100) NULL,
[test2] [nvarchar](100) NULL
) ON [PRIMARY]
GO
INSERT INTO [dbo].[TestValues] ([Code])
VALUES
(N'test1')
, (N'test2')
, (N'test3')
;
GO
SELECT
v.[Code]
, c.[name]
FROM
[dbo].[TestValues] AS v
LEFT OUTER JOIN [sys].[columns] AS c ON v.[Code] = c.[name]
WHERE
(c.[object_id] = OBJECT_ID(N'[dbo].[TestColumns]'))
AND (c.[column_id] > 1)
;
WITH
cteColumns AS (
SELECT
c.[name]
FROM
[sys].[columns] AS c
WHERE
(c.[object_id] = OBJECT_ID(N'[dbo].[TestColumns]'))
AND (c.[column_id] > 1)
)
SELECT
v.[Code]
, c.[name]
FROM
[dbo].[TestValues] AS v
LEFT OUTER JOIN cteColumns AS c ON v.[Code] = c.[name]
;
GO
ROLLBACK TRAN;
GO
In my opinion the two selects should have the same output. Can someone offer an explanation please?
TestValues is a table receiving data. TestColumns is a table that was created, when the project was started, by persisting a PIVOT query. Recently the process inserting into TestValues received some new data. I tried to get the new values using the first query and I was surprised when the result didn't show anything new.
Edit 1: Thank you dean for the answer, it sounds like a good explanation. Do you have any official page describing the behaviours of unpreserved tables? I did a quick google search and all I got was links towards Oracle. (added as an edit because I do not have enough reputation points to comment)

Access version 2000 & 2013 SQL pull latest date, MAX doesn't work

I have a table that needs to pull the latest date from different categories and the date might not always be filled out. I have tried to use MAX, MIN etc. it has not worked.
e.g. ID 1st Game Date 2nd Game Date 3rd Game Date
Joe 6/1/16 missing missing
Anna missing 7/2/16 7/6/16
Rita missing 7/31/16 missing
Needs to Return:
ID Date
Joe 6/1/16
Anna 7/6/16
Rita 7/31/16
I do have this sql that works well but it requires that all the dates get filled in other wise it doesn't return the latest date:
ApptDate: Switch([Pt1stApptDate]>=[2ndApptDate] And [Pt1stApptDate]>=
[3rdApptDate],[Pt1stApptDate],[2ndApptDate]>=[Pt1stApptDate] And [2ndApptDate]>=
[3rdApptDate],[2ndApptDate],[3rdApptDate]>=[Pt1stApptDate] And [3rdApptDate]>=
[2ndApptDate],[3rdApptDate])
Much appreciation in advance for all your help
Use the Nz function:
ApptDate: Switch(Nz([Pt1stApptDate],0)>=Nz([2ndApptDate],0) And
Nz([Pt1stApptDate],0)>= Nz([3rdApptDate],0), Nz([Pt1stApptDate],0),
Nz([2ndApptDate],0)>=Nz([Pt1stApptDate],0) And Nz([2ndApptDate],0)>=
Nz([3rdApptDate],0),Nz([2ndApptDate],0),
Nz([3rdApptDate],0)>=Nz([Pt1stApptDate],0) And Nz([3rdApptDate],0)>=
Nz([2ndApptDate],0),Nz([3rdApptDate],0))
Having said that, your table design is incorrect.
You should be storing each ApptDate per ID in a separate row:
ApptID ID ApptDate ApptNr
1 Joe 6/1/2016 1
2 Anna 7/2/2016 2
3 Anna 7/6/2016 3
4 Rita 7/31/2016 2
whereas ApptID is an autonumber and ApptNr is a sequence per ID (what you seem to call a category).
When you are having problems writing what should be simple queries (SQL DML) then you should consider you may have design flaws (in your SQL DDL).
The missing values are causing you to avoid the MAX set function and compels you to handle nulls in queries (note the NZ() function will cause errors outside of the Access UI). Better to model missing data by simply not adding a row to a table. Think about it: you want the smallest amount of data possible in your database, you can infer the remainder e.g. if Joe was not gaming on 1 Jan and 2 Jan and 3 Jan and 4 Jan etc then simply don't add anything to your database for all these dates.
The following SQL DDL requires ANSI-92 Query Mode (but you can create the same tables/views using the Access GUI tools):
CREATE TABLE Attendance
( gamer_name VARCHAR( 35 ) NOT NULL REFERENCES Gamers ( gamer_name ),
game_sequence NOT NULL CHECK ( game_sequence BETWEEN 1 AND 3 )
game_date DATETIME NOT NULL,
UNIQUE ( game_date, game_sequence ) );
INSERT INTO Attendance VALUES ( 'Joe', 1, '2016-06-01' );
INSERT INTO Attendance VALUES ( 'Anna', 2, '2016-07-02' );
INSERT INTO Attendance VALUES ( 'Anna', 3, '2016-07-06' );
INSERT INTO Attendance VALUES ( 'Rita', 1, '2016-07-31' );
CREATE VIEW MostRecentAttendance
AS
SELECT gamer_name, MAX ( game_date ) AS game_date
FROM Attendance
GROUP
BY gamer_name;
SELECT *
FROM Attendance a
WHERE EXISTS ( SELECT *
FROM MostRecentAttendance r
WHERE r.gamer_name = a.gamer_name
AND r.game_date = a.game_date );
To find the missing sequence values for players, create a table of all possible sequence numbers { 1, 2, 3 } to which you can 'anti-join' (e.g. NOT EXISTS).