IF no value exists in "IN" statement, show values as '0' - sql

I have th following result set for my query (exluding some select statments, joins, and where clauses because I just need the general method of how to accomplish this):
Select *
From hsi.itemdata
Where hsi.itemdata.itemtypenum in ('965','502','530','336','513','506','507','514','515','516')
ItemTypeNum | ItemType | DocTypeCount<br/>
502 | Consultation Report | 4 <br/>
506 | Discharge Summary | 10 <br/>
336 | ED Nurse Notes | 2 <br/>
513 | ED Provider Notes | 8 <br/>
514 | History and Physical | 15 <br/>
I want it to show all even if it doesn't exist in the in statement with a count of '0'. Like so...
ItemTypeNum | ItemType | DocTypeCount<br/>
502 | Consultation Report | 4 <br/>
506 | Discharge Summary | 10 <br/>
336 | ED Nurse Notes | 2 <br/>
513 | ED Provider Notes | 8 <br/>
514 | History and Physical | 15 <br/>
515 | *Appropriate Value* | 0 <br/>
516 | *Appropriate Value* | 0 <br/>
530 | *Appropriate Value* | 0 <br/>
507 | *Appropriate Value* | 0 <br/>
965 | *Appropriate Value* | 0 <br/>

In practice, you would use left join. The exact syntax depends on the database. Here is a version that works in SQL Server and Postgres, for instance:
Select v.itemtypenum,
coalesce(id.ItemType, '*Appropriate Value*') as ItemType,
coalesce(DocTypeCount, '') as DocTypeCount
From (values ('965'), ('502'), ('530'), ('336'), ('513'), ('506'), ('507'), ('514'), ('515'), ('516')
) v(itemtypenum) left join
hsi.itemdata id
on id.itemtypenum = v.itemtypenum;
Note: although not all databases support values in the from clause, almost all have some mechanism for creating a table on the fly. The idea is the same, but the syntax would be a bit different.

One way is by using CASE in your select for DocTypeCount:
SELECT ...
CASE
WHEN hsi.itemdata.itemtypenum IN ('965','502','530','336','513','506','507','514','515','516')
THEN DocTypeCount
ELSE 0
END AS DocTypeCount
FROM hsi.itemdata
Of course, this may get more complicated depending on your actual query and how you're getting these columns.

Related

Query to join two tables with like operator

I have two table which has data as below
Table1
+-----+-------+-------------------------+
| ID | value | Test |
+-----+-------+-------------------------+
| 200 | 2456 | yyy xxcv zuio uio tzrue |
| 201 | 2905 | xxx tttt ssrt uio uioe |
| 203 | 34567 | zzz iii ool uiol werts |
| 204 | 2356 | xxx tttt ssrt uio wertz |
| 205 | 3478 | io ser xcv erto klop |
| 206 | 4567 | xxx tttt ssrt uio poiu |
| 207 | 234 | zzz iii ool uiol wert |
+-----+-------+-------------------------+
I would like to create where clause to get rows with like operator.
for ex.
select *
from Table1
where test like '%xxcv zuio%' Or Like '%iii ool%' OR '%xcv erto%' OR '%ssrt uio%' OR '%uio uioe%'
But my problem is that there are more than 15-20 different parameter in where clause, it can also increase latter.
So I have decided to create a new table in database lets called it Table2 with parameter as shown below.
Table2
+----+-----------+
| ID | Parameter |
+----+-----------+
| 20 | xxcv zuio |
| 21 | iii ool |
| 22 | xcv erto |
| 23 | ssrt uio |
| 24 | uio uioe |
+----+-----------+
My question is how can I join this table to give the same result like above query.
I am still learning joins so any advice will be helpful.
You can use exists:
select t1.*
from Table1 t1
where exists (select 1 from table2 t2 where t1.test like concat('%', t2.parameter, '%'))
I don't think using a join is helping in this scenario, and this kind of text searching is not a strong point for SQL Server. Consider building an elasticsearch index or using another system that supports text searching as a primary use case (SQL Server does support full text search if that feature is enabled, but I've always been warned away from it, so don't have experience with it.)
If staying within TSQL is desirable for your particular situation, then I would use the awkward "OR LIKE" syntax. What it lacks in elegance it makes up for in readability.

one to many join

I have two table the first one is with 3 columns As
CR_GENERAL:
CRNO, | mainCR | CR status
-------|--------|------------
555 | Null | not act
5647 | 555 | act
7845 | 555 | not act
434 | Null | act
566 | 434 | act
675 | null | not act
778 | null | act
768 | null | Can
8668 | 555 | can
Second table (IDENTIFICATIONS):
Cr | partner
--------|---------
555 | 23453
434 | 23555
768 | 26653
8668 | 23453
5647 | 23453
First thing I want to do is :
to make all the mainCR Active when ever the Sub is Active.
How ?
In this case in the first table when ever the MainCR is null then the CRNO is the MAINCR and the other thing when ever the CRNO is active the mainCR need to be active as well even if it is not active in this case
555 should be active because 5647 is active and 768 should be active as well
Second step :
I need to create table which includes mainCR with all other CR with it and Including all the status for these CR and Join it with the IDENTIFICATIONS table to add the ID because at the end I need to get the ID status with all CR including with this ID
The result at the end I want it to be something similar to this:
partner| main CR | Sub CR | Sub CR2 | Sub CR3 | Status
--------|---------|------------------------------
23453 | 555 | 5647 | 7845 | 8668 | Act-not Act -can -Act
23555 | 434 | 566 | Null | Null | Act - Act
26653 | 768 | Null | Null | Null | Can
I tried a lot of queries but with no luck I need ur help in this one
I am fine to have status in different columns as long as these are in the same row

Epicor BAQ - calculated fields

Hope you are doing well and help me with below query about BAQ.
Please see example below - current results
+-------+------+--------------+------+
| Order | Part | Ship By Date | Wave |
+-------+------+--------------+------+
| 1231 | A | 11/04/2018 | 333 |
| 1231 | A | 11/04/2018 | 257 |
| 2522 | C | 11/04/2018 | 333 |
| 2556 | A | 11/04/2018 | 0 |
+-------+------+--------------+------+
I need to find the way using calculated fields or other options in BAQ to see only one wave no. for each order line. Something like show me top wave when ship by date and order no. are the same else 0 end
+-------+------+--------------+------+
| Order | Part | Ship By Date | Wave |
+-------+------+--------------+------+
| 1231 | A | 11/04/2018 | 333 |
| 2522 | C | 11/04/2018 | 333 |
| 2556 | A | 11/04/2018 | 0 |
+-------+------+--------------+------+
Hope you will be able to help, many thanks in advance.
Hopefully this idea helps.
In Epicor 10, you should be able to create a Common Table Expression (CTE).
From your example, I would create 2 CTEs. One for each of the result sets. For the second CTE, select MAX(Order) group by Ship By Date.
Next, create a new TopLevel to join both CTEs on Order number to obtain your desired results.
I don't have Epicor 10 readily available to me, but I had achieved something like this by creating subqueries.
You will need to utilize (what I believe Epicor calles) inner queries. You inner subquery will be need to be set as a Top option with a sort option of wave descending and returning the four fields listed in your example. You will then join the table to itself with the order, part, and shipby fields as the key values. This should work.
If you have access to an instance of SSMS, you could try something like:
SELECT DISTINCT Order, Part, ShipByDate, Wave
FROM [Table] t
WHERE Wave = (SELECT TOP 1 WAVE FROM [Table] t2 WHERE t.Order = t2.Order and t.Part = t2.Part and t.ShipByDate = t2.ShipByDate ORDER BY Wave DESC)

SQL Storing Age Range

Im building an friendship site and I want to store restrictions for when a profile can be viewed.
Right now im using entity-attribute model to store restrictions. Examples of restrictions are what days a profile is available. The issue im having is i want to add a restriction on if a user can view a profile based on a users age range.
Im not sure if this approach is correct for storing, it feels really redundant but maybe im just being picky.
The two restrictions i want to add are minimum age and maximum age. Does this design seem like the correct approach?
User Attribute Entity Table
id(PK) | userid | attribute | entity
0 | 0 | 0 | 1
1 | 0 | 1 | 188
Attribute Table
id(PK) | attribute
0 | Minimum Age
1 | Maximum Age
2 | Contact Restricted Days
Entity Table
id(PK) | attribute_ID | Entity
0 | 0 | 18
1 | 0 | 19
.. | .. | ..
88 | 0 | 99
89 | 1 | 18
90 | 1 | 19
.. | .. | ..
188 | 1 | 99
199 | 2 | Monday
.. | .. | ..
205 | 2 | Sunday
I am posting this suggestion as an answer. But here is how I would have designed your table. Having id column in each table can cause headaches down the road, especially since you would need to explicitly define the column. Please compare the design below with your tables above:
User Attribute Entity Table
user_attr_entity_id(PK) | userid | attribute_id| entity_id
0 | 0 | 0 | 1
1 | 0 | 1 | 188
Attribute Table
attribute_id(PK) | attribute
0 | Minimum Age
1 | Maximum Age
2 | Contact Restricted Days
Entity Table
Entity_id(PK) | attribute_id | Entity_Value
0 | 0 | 18
1 | 0 | 19
.. | .. | ..
88 | 0 | 99
89 | 1 | 18
90 | 1 | 19
.. | .. | ..
188 | 1 | 99
199 | 2 | Monday
.. | .. | ..
205 | 2 | Sunday
UPDATE:
Seems like I must have misread your question initially. I think this design will work just fine. I tested using the query below:
SELECT userid
,a.attribute_id
,e.entity_id
,attribute
,entity_value
FROM user_attribute_entity_table uae
JOIN attribute_table a ON uae.attribute_id = a.attribute_id
JOIN entity_table e ON e.[entity_id] = uae.[entity_id]
If you're building for speed, i.e. if you need to optimize it for storing large amount of data, and if you know the "restrictions" (entitys) will not change a lot, then I'd say design it flatter/horizontally:
Id | UserId | Restriction1 | Restriction2 | Restriction3 | ..
This will however cost you flexibility, make it tougher on future growth/change and limit options.
Your original design is very flexible, and can be compared to a site with language dimensions - X amount of languages on Y amount of elements. Each element/entity should have it's own translation, and they should be easy to add/change.
However, design is somewhat about personal preference also. This is how I would solve it in a similar manner:
Users
-------------
UserId | Name
Attributes
-----------------------
AttributeId | Attribute
Entities
-----------------
EntityId | Entity/(or Value)
UserAttributeEntities
------------------------------------
Id | UserId (FK) | AttributeId (FK) | EntityId (FK)/or EntityValue
Entity, in my example, can either be it's own table (if values are resued often), or you can just put a column EntityValue direclty in the UserAttributeEntities table, and skip the Entities table.

How to assign event counts to relative date values in SQL?

I want to line up multiple series so that all milestone dates are set to month zero, allowing me to measure the before-and-after effect of the milestone. I'm hoping to be able to do this using SQL server.
You can see an approximation of what I'm starting with at this data.stackexchange.com query. This sample query returns a table that basically looks like this:
+------------+-------------+---------+---------+---------+---------+---------+
| UserID | BadgeDate | 2014-01 | 2014-02 | 2014-03 | 2014-04 | 2014-05 |
+------------+-------------+---------+---------+---------+---------+---------+
| 7 | 2014-01-02 | 232 | 22 | 19 | 77 | 11 |
+------------+-------------+---------+---------+---------+---------+---------+
| 89 | 2014-04-02 | 345 | 45 | 564 | 13 | 122 |
+------------+-------------+---------+---------+---------+---------+---------+
| 678 | 2014-03-11 | 55 | 14 | 17 | 222 | 109 |
+------------+-------------+---------+---------+---------+---------+---------+
| 897 | 2014-03-07 | 234 | 56 | 201 | 19 | 55 |
+------------+-------------+---------+---------+---------+---------+---------+
| 789 | 2014-02-22 | 331 | 33 | 67 | 108 | 111 |
+------------+-------------+---------+---------+---------+---------+---------+
| 989 | 2014-01-09 | 12 | 89 | 97 | 125 | 323 |
+------------+-------------+---------+---------+---------+---------+---------+
This is not what I'm ultimately looking for. Values in month columns are counts of answers per month. What I want is a table with counts under relative month numbers as defined by BadgeDate (with BadgeDate month set to month 0 for each user, earlier months set to negative relative month #s, and later months set to positive relative month #s).
Is this possible in SQL? Or is there a way to do it in Excel with the above table?
After generating this table I plan on averaging relative month totals to plot a line graph that will hopefully show a noticeable inflection point at relative month zero. If there's no apparent bend, I can probably assume the milestone has a negligible effect on the Y-axis metric. (I'm not even quite sure what this kind of chart is called. I think Google might have been more helpful if I knew the proper terms for what I'm talking about.)
Any ideas?
This is precisely what the aggregate functions and case when ... then ... else ... end construct are for:
select
UserID
,BadgeDate
,sum(case when AnswerDate = '2014-01' then 1 else 0 end) as '2014-01'
-- etc.
group by
userid
,BadgeDate
The PIVOT clause is also available in some flavours and versions of SQL, but is less flexible in general so the traditional mechanism is worth understanding.
Likewise, the PIVOT TABLE construct in EXCEL can produce the same report, but there is value in maximally aggregating the data on the server in bandwidth competitive environments.