Conditional Unique in MySql DB and EF Core - c#

I have a table dealers which has column token(need to be unique) and has isTokenActive(bool).
I was wandering if there is a way to add unique constraint on a token column but only if there is another row that has same token and isTokenActive is set to 1. If there is a row with same token and isTokenActive is set to 0 that is a valid case too.
Basically I want to allow this
id | Token | isTokenActive |
--------------------------------------
1 | ABC | 0 |
2 | ABC | 1 |
And this
id | Token | isTokenActive |
--------------------------------------
1 | ABC | 0 |
2 | ABC | 0 |
But not this
id | Token | isTokenActive |
--------------------------------------
1 | ABC | 1 |
2 | ABC | 1 |
And it would be great if it is possible to do it code first with EF Core.

Related

How to list the products under each category in sql? side by side

I'm a bit of a beginner in sql and I need your help.
I'm sorry that I don't know if the question is correct.
now the code gives this;
+---------+----------+-------------+------------+
| id | CompanyId| DealId | price |
+---------+----------+-------------+------------+
| 1 | 1 | 1 | 100 |
| 2 | 1 | 2 | 50 |
| 3 | 1 | 3 | 25 |
| 4 | 2 | 1 | 1000 |
| 5 | 2 | 2 | 2000 |
| 6 | 2 | 3 | 2500 |
+---------+----------+-------------+------------+
but this is what i want;
+---------+----------+-------------+------------+------------+--+
| id | companyId| DealName1 | DealName2 | DealName3 | |
+---------+----------+-------------+------------+------------+--+
| 1 | 1 | 100 | 50 | 25 | |
| 2 | 2 | 1000 | 2000 | 2500 | |
| 3 | 3 | value | value | value | |
| 4 | 4 | value | value | value | |
+---------+----------+-------------+------------+------------+--+
select CompanyId
,[1] as DealName1
,[2] as DealName2
,[3] as DealName3
from (select CompanyId, DealId, price from t) t
pivot (sum(price) for DealId in([1],[2],[3])) p
CompanyId
DealName1
DealName2
DealName3
1
100
50
25
2
1000
2000
2500
Fiddle

How can I set the WHERE clause to filter on multiple bit columns using only checkboxes that are checked without using dynamic SQL?

I am attempting to filter results of a select statement using checkboxes and parameters with a SqlDataSource control.
The problem is that parameters can't be undefined, and I only want any of the given parameters to equal "1" or "True" if they are defined. Any other time, they shouldn't be used in the WHERE clause at all (or maybe set to something like "IS NOT NULL").
Essentially, when a checkbox is checked, the WHERE clause should include a parameter associated with that checkbox and the value of the parameter should be "1" (True), otherwise, if a checkbox is in any other state, "unchecked" or "indeterminate" the WHERE clause should not include a parameter for that checkbox at all, or it should be set to some value that essentially selects either "1" (True) or "0" (False).
I have tried playing with the WHERE clause by adding parenthesis, adding "AND" and "OR" statements, but I can't seem to figure it out. Dynamic SQL would easily solve this problem, but it would be a nightmare to maintain and it's just bad practice.
As an example, let's say you have the following data set:
| ID | Col1 | BitField1 | BitField2 | BitField3 |
| 1 | Row1 | 1 | 0 | 1 |
| 2 | Row2 | 1 | 1 | 1 |
| 3 | Row3 | 1 | 0 | 1 |
| 4 | Row4 | 1 | 1 | 0 |
| 5 | Row5 | 0 | 0 | 0 |
On our UX we would have 3 checkboxes, one for each "BitField" in the data.
If the user checks none of the checkboxes, the search result should return:
| ID | Col1 | BitField1 | BitField2 | BitField3 |
| 1 | Row1 | 1 | 0 | 1 |
| 2 | Row2 | 1 | 1 | 1 |
| 3 | Row3 | 1 | 0 | 1 |
| 4 | Row4 | 1 | 1 | 0 |
| 5 | Row5 | 0 | 0 | 0 |
and the WHERE statement should essentially have no parameters, or if it does, it would be something like WHERE BitField1 IS NOT NULL AND BitField2 IS NOT NULL AND BitField3 IS NOT NULL.
If the user checks the box associated with "BitField2" the result should be:
| ID | Col1 | BitField1 | BitField2 | BitField3 |
| 2 | Row2 | 1 | 1 | 1 |
| 4 | Row4 | 1 | 1 | 0 |
and the WHERE statement should be WHERE BitField2 = 1.
If the user checks the boxes associated with "BitField1" and "BitField2" the result should be:
| ID | Col1 | BitField1 | BitField2 | BitField3 |
| 2 | Row2 | 1 | 1 | 1 |
| 4 | Row4 | 1 | 1 | 0 |
and the WHERE statement should be WHERE BitField1 = 1 AND BitField2 = 1.
If the user checks all the boxes, the result should be:
| ID | Col1 | BitField1 | BitField2 | BitField3 |
| 2 | Row2 | 1 | 1 | 1 |
and the WHERE statement should be WHERE BitField1 = 1 AND BitField2 = 1 AND BitField3 = 1.
Is this something I can do without using dynamic SQL? I'm not using a stored procedure, but a standard TSQL query.
Any help would be GREATLY appreciated.
If a box is not checked make it's parameter value DBNull.Value. Then in the WHERE clause do this for each
... AND BitFieldX = ISNULL(#BitFieldX, [BitFieldx])...
This has the effect of using 1 or else whatever the bitfield is which effectively negates any filter on that field.

TSQL MERGE Multiple Tables with Insert, Update, Delete

I'm currently working on a stored procedure in T-SQL on SQL Server 2012. The task is really tricky: I need to merge (insert,update,delete) entries in multiple tables.
To facilitate, I try to explain my problem with 2 tables. I use Dapper in C# in an ASP.NET 4.5 MVC application and can control my Front-End. I'm passing into the stored procedure 2 Temporary Tables:
Temporary Table Target:
ID | TargetId | TargetGroupId | IsPublic | IsPrivate |
---+----------+---------------+----------+-----------+
0 | 42 | 1 | 0 | 1 |
1 | 0 | 1 | 1 | 0 |
2 | 0 | 1 | 0 | 1 |
Temporary Table Target Countries
ID |CountryId | TargetId |
---+----------+----------+
0 | CA | 42 |
1 | FR | 0 |
2 | AU | 0 |
The TargetId 0 corresponds to a new entry, thus if the TargetId = 0 I want to Insert or Delete an old record not from the list, if the TargetId > 0 I want to Update the record.
The final Result could look like this:
Table Target:
| TargetId | TargetGroupId | IsPublic | IsPrivate |
+----------+---------------+----------+-----------+
| 42 | 1 | 0 | 1 |
| 93 | 1 | 1 | 0 |
| 94 | 1 | 0 | 1 |
Table Country:
CId |CountryId | TargetId |
-----+----------+----------+
34 | CA | 42 |
35 | FR | 93 |
36 | AU | 94 |
So the new TargetId should be stored in Country as well. My current TSQL script looks like this:
DECLARE #TargetGroupId = 1;
MERGE [MySchema].[Target] AS [A]
USING #Targets AS [B]
ON ([A].TargetId = [B].TargetId)
WHEN NOT MATCHED BY TARGET THEN
INSERT (TargetGroupId, IsPrivate, IsPublic)
VALUES (#TargetGroupId, [B].IsPrivate, [B].IsPublic)
-- Desired behaviour: doesn't work unfortunately...
-- OUTPUT inserted.TargetId, [B].ID
-- INTO #tmp;
WHEN MATCHED THEN
UPDATE
SET [A].IsPrivate = [B].IsPrivate, [A].IsPublic = [B].IsPublic
WHEN NOT MATCHED BY SOURCE AND [A].TargetGroupId = #TargetGroupId
THEN DELETE;
This SQL script works fine for my table Target, but how can I update my second table Countries?
Do you know how solve this issue, thus to Insert, Update, Delete in a Merge Statement including several tables?
Thank you very much!!

Notify in .NET application if SQL data has changed

I have got two tables. Table A contains the main data in every change state, Table B has the detail data.
Table A
| ID | Name |
| 1 | House |
| 2 | Tree |
| 3 | Car |
Table B
| ID | FK | DateTime | Color | Type |
| 1 | 1 | 2017-26-01T13:00:00 | Red | Bungalow |
| 2 | 2 | 2017-26-01T13:05:00 | Brown | Oak |
| 3 | 1 | 2017-26-01T13:10:00 | Green | Bungalow |
| 4 | 3 | 2017-26-01T13:15:00 | Yellow | Smart |
| 5 | 1 | 2017-26-01T13:20:00 | White | Bungalow |
| 6 | 3 | 2017-26-01T13:25:00 | Black | Smart |
Result to watch
| ID | Name | DateTime | Color | Type |
| 1 | House | 2017-26-01T13:20:00 | White | Bungalow |
| 2 | Tree | 2017-26-01T13:05:00 | Brown | Oak |
| 3 | Car | 2017-26-01T13:25:00 | Black | Smart |
The current state of an entity in Table A is described by the record with the youngest timestamp in Table B.
Now, I want to be nofitied, if an entity gets a new state (new record in Table B) or a new entity is created (new records in Table A and B), i.e. it could look like.
New result to watch
| ID | Name | DateTime | Color | Type |
| 1 | House | 2017-26-01T13:20:00 | White | Bungalow |
| 2 | Tree | 2017-26-01T13:05:00 | Brown | Oak |
| 3 | Car | 2017-26-01T19:25:00 | Silver | Smart |
| 4 | Dog | 2017-26-01T20:25:00 | White / Black | Poodle |
With SqlDependency it is not possible to be notified for a statement which contains GROUP BY with MAX aggregate, window functions or TOP clause. So I have no idea how I can get the last detail data for an entity.
Is there any possibility to create a statement for this requirement or are there any other ways to be notified after changes for this result?
You can create and use SQL Triggers usin CLR
Here - SQL Trigger CLR

assign unique group id to related values between two columns

I have a challenging problem.I am developing a web app (.net(C#)) that takes an specific excel file and export an delimited file with specifications explained below.
Here is the excel to be imported:
Loan_ID |Owner_Id | RelPerson_Id | Loan_Class
------------------------------------------------
L131231 | 1234 | 5678 | 0
L135148 | 2345 | 6789 | 2
L417128 | 1234 | 5432 | 1
L271237 | 5678 | 1112 | 5
L213781 | 2345 | 1113 | 4
L098932 | 1117 | 6789 | 6
L012213 | 1122 | 3311 | 2
L398721 | 2221 | 1112 | 3
L098766 | 5552 | | 1
Desired output:
Cust_ID | Cust_class | Gr_ID | Gr.Members | Gr_Class
---------------------------------------------------------------------
1234 | 1 | 1 | (1234,5678,5432,1112,2221) | 5
2345 | 4 | 2 | (2345,1117,6789,1113) | 6
5678 | 5 | 1 | (1234,5678,5432,1112,2221) | 5
1117 | 6 | 2 | (2345,1117,6789,1113) | 6
1122 | 2 | 3 | (1122,3311) | 2
6789 | 6 | 2 | (2345,1117,6789,1113) | 6
5432 | 1 | 1 | (1234,5678,5432,1112,2221) | 5
1112 | 5 | 1 | (1234,5678,5432,1112,2221) | 5
1113 | 4 | 2 | (2345,1117,6789,1113) | 6
3311 | 2 | 3 | (1122,3311) | 2
2221 | 3 | 1 | (1234,5678,5432,1112,2221) | 5
5552 | 1 | 4 | (5552) | 4
So,i will explain the case in order for you to understand.In the excel file, the first column represents the loan with unique id (no duplicates), the second column represent the Owner of the loan which is an id to identify the customer(Customer_Id).The id of Related person is also a Customer_Id which is the guarantor of the owner in this loan. A customer may have 2 or more loans and can be the guarantor in 2 or more other loans. The guarantor may be the guarantor in 2 or three loans but also may be the owner of another loan.So the owner_id and Rel_PersonId may have duplicates and the Rel_PersonId may have blank values . Class column is the rating or classification of the loan Id (Based on days in delay).
From this file i want the above output.
Cust_id is the distinct Customer Id which will be taken from both columns, Owner, and Rel Persons and will be assigned the highest class(Column :Cust_Class) of the loan he is part of(whether owner or guarantor).I already found a solution for the first two columns of the output, i am stuck with grouping.
Grouping logic:Two customers involved in one loan are grouped together, but if any of this customers is involved in another loan(wether like an Owner or a guarantor) with another Cutomer X, and in another with another customer Y both customers will be in a group with the first two, and if customer x or y are involved in other loans with other customers z and a those are added to the first group with the others too, and this cycle continues till there are no more customer connected with those that are already in the group.See the desired output for understanding.The group id will be generated automatically and sequentially(1,2,3,4) .The group class will be the class of the customer with the highest Cust_class of the group.
I am using sql server to import the excel.Any idea on how to build a query to gain this output or any other solutions?
Hope you can understand, feel free to ask for any further clarification.
Thank you.

Categories