I need to generate a random number based on below three conditions
Generate new PRCnumber when color changes
Generate new PRCnumber when the day changes
Generate new PRCnumber when color remains same but shirt number
changes within the day.
The random number will be used as identifier for the lot of the products generated. Shirt table will have the shirt number and respective color details.
Below is the query I will be using to fetch and it will take shirt number Shirt_num as input
select shirt.facility,
shirt.color,
shirt.lotnum,
colorMgr.untpal,
colorMgr.style,
shirt.product_line
from shirt,
colorMgr,
products
where colorMgr.facility = shirt.facility
and colorMgr.color = shirt.color
and colorMgr.color_id = shirt.color_id
and shirt.product_line = products.product_line
and shirt.shirtnum = #shirtnum;
I want to write conditions something like but not sure how to catch and compare when new color keeps changing.
if day_changes ()
SELECT RAND() as prcnumber
else if shirt_num_changes()
SELECT RAND() as prcnumber
else if color_changes ()
SELECT RAND() as prcnumber
..........
The desired output will be something like this.
shirt_num RandomNum Color Day
1111011 384700412 Black 26 Feb, 2021
1111011 384700132 Black 27 Feb, 2021 (Random numbr when day changes)
1111017 384701792 Black 26 Feb, 2021 (Random numbr when shirt_num changes)
1111011 384700458 Blue 26 Feb, 2021 (Random numbr when color changes)
You can do what you want with window functions, but it would depend on the ordering of the query, and it would not be deterministic (you'd get a different number each query).
I would instead recommend using a checksum of the fields.
mysql> select *, sha1(concat_ws('|', shirtnum, color, day)) from shirts;
+----------+-------+------------+--------------------------------------------+
| shirtnum | color | day | sha1(concat_ws('|', shirtnum, color, day)) |
+----------+-------+------------+--------------------------------------------+
| 111 | black | 2021-02-26 | ad48a0f6b9b197ce11a78a85bca70a487af8f028 |
| 111 | black | 2021-02-26 | ad48a0f6b9b197ce11a78a85bca70a487af8f028 |
| 111 | blue | 2021-02-26 | d863fb4761e0deae3815b6f1ab53c69d5a1a2958 |
| 222 | black | 2021-02-26 | a5dbace4af2bd0510178dcb05065392f2a73d3c0 |
| 222 | black | 2021-02-27 | 1906c453b7bff2b140bb972be8ba29fa80260392 |
| 222 | black | 2021-02-27 | 1906c453b7bff2b140bb972be8ba29fa80260392 |
| 111 | black | 2021-02-27 | c0061ba0d2be5d261c0f7ddcb28ccd8de0ea7c52 |
+----------+-------+------------+--------------------------------------------+
The advantage is this is deterministic and does not depend on the order of the results.
You can implement this as a generated column if your database supports that, or with a view.
mysql> create view shirt_ids as select *, sha1(concat_ws('|', shirtnum, color, day)) as whatever_this_is from shirts;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from shirt_ids;
+----------+-------+------------+------------------------------------------+
| shirtnum | color | day | whatever_this_is |
+----------+-------+------------+------------------------------------------+
| 111 | black | 2021-02-26 | ad48a0f6b9b197ce11a78a85bca70a487af8f028 |
| 111 | black | 2021-02-26 | ad48a0f6b9b197ce11a78a85bca70a487af8f028 |
| 111 | blue | 2021-02-26 | d863fb4761e0deae3815b6f1ab53c69d5a1a2958 |
| 222 | black | 2021-02-26 | a5dbace4af2bd0510178dcb05065392f2a73d3c0 |
| 222 | black | 2021-02-27 | 1906c453b7bff2b140bb972be8ba29fa80260392 |
| 222 | black | 2021-02-27 | 1906c453b7bff2b140bb972be8ba29fa80260392 |
| 111 | black | 2021-02-27 | c0061ba0d2be5d261c0f7ddcb28ccd8de0ea7c52 |
+----------+-------+------------+------------------------------------------+
Related
I'm currently trying to query up a list of the top 15 occurring faults on a PLC in the warehouse. I've gotten that part down:
Select top 15 fault_number, fault_message, count(*) FaultCount
from Faults_Stator
where T_stamp> dateadd(hour, -18, getdate())
Group by Fault_number, Fault_Message
Order by Faultcount desc
HOOOWEVER I now need to find out the accumulated downtime of said faults in the top 15 list, information in another column "Fault_duration". How would I go about doing this? Thanks in advance, you've all helped me so much already.
+--------------+---------------------------------------------+------------+
| Fault Number | Fault Message | FaultCount |
+--------------+---------------------------------------------+------------+
| 122 | ST10: Part A&B Failed | 23 |
| 4 | ST16: Part on Table B | 18 |
| 5 | ST7: No Spring Present on Part A | 15 |
| 6 | ST7: No Spring Present on Part B | 12 |
| 8 | ST3: No Pin Present B | 8 |
| 1 | ST5: No A Housing | 5 |
| 71 | ST4: Shuttle Right Not Loaded | 4 |
| 144 | ST15: Vertical Cylinder did not Retract | 3 |
| 98 | ST8: Plate Loader Can not Retract | 3 |
| 72 | ST4: Shuttle Left Not Loaded | 2 |
| 94 | ST8: Spring Gripper Cylinder did not Extend | 2 |
| 60 | ST8: Plate Loader Can not Retract | 1 |
| 83 | ST6: No A Spring Present | 1 |
| 2 | ST5: No B Housing | 1 |
| 51 | ST4: Vertical Cylinder did not Extend | 1 |
+--------------+---------------------------------------------+------------+
I know I wouldn't be using the same query, but I'm at a loss at how to do this next step.
Fault duration is a column which dictates how long the fault lasted in ms. I'm trying to have those accumulated next to the corresponding fault. So the first offender would have those 23 individual fault occurrences summed next to it, in another column.
You should be able to use the SUM accumulator:
Select top 15 fault_number, fault_message, count(*) FaultCount, SUM (Fault_duration) as FaultDuration
from Faults_Stator
where T_stamp> dateadd(hour, -18, getdate())
Group by Fault_number, Fault_Message
Order by Faultcount desc
I have an influxdb table lets call it my_table
my_table is structured like this (simplified):
+-----+-----+-----
| Time| m1 | m2 |
+=====+=====+=====
| 1 | 8 | 4 |
+-----+-----+-----
| 2 | 1 | 12 |
+-----+-----+-----
| 3 | 6 | 18 |
+-----+-----+-----
| 4 | 4 | 1 |
+-----+-----+-----
However I was wondering if it is possible to find out how many of the metrics are larger than a certain (dynamic) threshold for each time.
So lets say I want to know how many of the metrics (columns) are higher than 5,
I would want to do something like this:
select fieldcount(/m*/) from my_table where /m*/ > 5
Returning:
1
1
2
0
I am relatively restricted in structuring the database as I'm using diamond collector (python) which takes care of all datacollection for me and flushes it to my influxdb without me telling what the tables should look like.
EDIT
I am aware of a possible solution if I hardcode the threshold and add a third metric named mGreaterThan5:
+-----+-----+------------------+
| Time| m1 | m2 |mGreaterThan5|
+=====+=====+====+=============+
| 1 | 8 | 4 | 1 |
+-----+-----+----+-------------+
| 2 | 1 | 12 | 1 |
+-----+-----+----+-------------+
| 3 | 6 | 18 | 2 |
+-----+-----+----+-------------+
| 4 | 4 | 1 | 0 |
+-----+-----+----+-------------+
However this means that I cant easily change this threshold to 6 or any other number so thats why I would prefer a better solution if there is one.
EDIT2
Another similar problem occurs with trying to retrieve the highest x amount of metrics. Eg:
On Jan 1st what were the highest 3 values of m? Given table:
+-----+-----+----+-----+----+-----+----+
| Time| m1 | m2 | m3 | m4 | m5 | m6 |
+=====+=====+====+=====+====+=====+====+
| 1/1 | 8 | 4 | 1 | 7 | 2 | 0 |
+-----+-----+----+-----+----+-----+----+
Am I screwed if I keep the table structured this way?
I have a question regarding joining some large tables then attempting to concatenate multiple entries of an attribute. The data is stored in Access which is where I am attempting to restructure the data via queries for my use case.
I am able to join the tables fine as seen in example.. but not sure what is the best method for concatenating multi-valued attributes.. my data set is huge so I have been having performance issues.
I have created some comparable data I am working with to give an idea on how I am joining data. I have noted the number of rows that I have for each table.
TabOrders (121,965 rows)
------------------------------------------
OrderNum | Product | ConfigInstance
------------------------------------------
1 | Product1| 100
2 | Product2| 200
TabConfigurations (121,965 rows)
-------------------------------------
ConfigInstance | Configuration
-------------------------------------
100 | C100
200 | C200
TabConfigDetails (4,021,244 rows)
--------------------------------------
Configuration | ConfigIndicator
--------------------------------------
C100 | A1V2
C100 | A2V1
C100 | A3V1
C100 | A3V2
C100 | A4V2
C200 | A1V1
C200 | A2V2
C200 | A2V4
C200 | A3V4
C200 | A3V5
C200 | A4V2
TabAttributes (27,665 rows)
-------------------------------------------
ConfigIndicator | Attribute | Value
-------------------------------------------
A1V1 | Product | Car
A1V2 | Product | Bike
A1V3 | Product | Motorcycle
A1V4 | Product | Go Cart
A2V1 | Color | Red
A2V2 | Color | Green
A2V3 | Color | Blue
A2V4 | Color | Orange
A3V1 | Accessories| Helmet
A3V2 | Accessories| Cup Holder
A3V3 | Accessories| Cargo
A3V4 | Accessories| Trailer
A3V5 | Accessories| GPS
A4V1 | Size | Small
A4V2 | Size | Large
Here is the query Ive used to join everything:
SELECT TabOrders.OrderNum, TabOrders.Product, TabAttributes.Attribute, TabAttributes.Value
FROM ((TabOrders INNER JOIN TabConfigurations ON TabOrders.[ConfigInstance] = TabConfigurations.[ConfigInstance]) INNER JOIN TabConfigDetails ON TabConfigurations.[Configuration] = TabConfigDetails.[Configuration]) INNER JOIN TabAttributes ON TabConfigDetails.[ConfigIndicator] = TabAttributes.[ConfigIndicator]
And gets me:
OrderNum | Product | Attribute | Value
------------------------------------------
1 | Product1| Product | Bike
1 | Product1| Color | Red
1 | Product1| Accessories| Helmet
1 | Product1| Accessories| Cup Holder
1 | Product1| Size | Large
2 | Product2| Product | Car
2 | Product2| Color | Green
2 | Product2| Color | Orange
2 | Product2| Accessories| Trailer
2 | Product2| Accessories| GPS
2 | Product2| Size | Large
But I would like to get the data formated as below.. but the methods* I have used takes way too long and access crashes..
OrderNum | Product | Attribute | Value
------------------------------------------
1 | Product1| Product | Bike
1 | Product1| Color | Red
1 | Product1| Accessories| **Helmet;Cup Holder**
1 | Product1| Size | Large
2 | Product2| Product | Car
2 | Product2| Color | **Green;Orange**
2 | Product2| Accessories| **Trailer;GPS**
2 | Product2| Size | Large
*Ive mostly attempted utilizing functions, I attempted using GetList function (I created another column CONCAT1 to be used as index.. concatenating ConfigInstance and Attribute then saved the query as DataConfigurations)
GetList: GetList
Is there a better way to structure the query for better performance? It seems when function runs, it reprocesses the entire query each time its triggered.
Here is the query:
SELECT DISTINCT DataConfigurations.OrderNum, DataConfigurations.Product, DataConfigurations.Attribute, GetList("Select Value From DataConfigurations As T1 Where DataConfigurations.CONCAT1 = " & [DataConfigurations].[CONCAT1],"",", ") AS Value_CONCAT
FROM DataConfigurations
This seemed to work only when processing on small amount of orders.. if I tried on entire data set it would run and hangup my computer.
Reference this other question, seems to achieve what you are wanting to accomplish. Performance issues could be result of a improper link (aka duplication) or your PC just needs to be beefier.
I have seen many similar questions but none that meet my needs exactly, and I cannot seem to deduce a solution on my own from inspecting the other questions.
I have the following (mock) table below. My actual table has many more columns.
TableA:
ID | color | feel | size | alive | age
------------------------------------------
1 | blue | soft | large | true | 36
2 | red | soft | large | true | 36
2 | blue | hard | small | false | 37
2 | blue | soft | large | true | 36
2 | blue | soft | small | false | 39
15 | blue | soft | medium | true | 04
15 | blue | soft | large | true | 04
15 | green | soft | large | true | 15
40 | pink | sticky | large | true | 83
51 | brown | rough | tiny | false | 01
51 | gray | soft | tiny | true | 59
34 | blue | soft | large | true | 02
I want the result to look like:
Result of query on TableA:
ID | color | feel | size | alive | age
-------------------------------------------
1 | blue | soft | large | true | 36
2 | red | soft | large | true | 36
15 | blue | soft | medium | true | 04
40 | pink | sticky | large | true | 83
51 | brown | rough | tiny | false | 01
34 | blue | soft | large | true | 02
I want one row for every unique ID column, but I do not want to check the other columns. I need the other columns returned in my result set, but I do not want to filter on them. I just need one row for every unique ID - I do not care which row.
In my example, I selected the first row of every unique ID.
I have tried variations of
select *
from TableA
group by ID having ID = max(ID)
Most examples I have seen with group by and max and/or min functions involve only 2 columns. I have many more columns, however.
I have also seen examples using CTE, but I am not using SQL Server (I am using Sybase).
How can I achieve the result set described?
EDIT
We are using Sybase version 15.1.
Your solution with MIN has some drawbacks. It doesn't return you a specific row but MIN values from the group of rows. You can get as result rows which are not in database. Is it OK for you ?
Row_number is supported in sybase 15.2
http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc38151.1520/html/iqrefbb/iqrefbb262.htm
It's sad if it is not supported in 15.1. You can use then identity column and temporary table to achieve what you want.
There are a variety of ways to do this. If you have a more recent version of Sybase, you can use row_number():
select t.*
from (select t.*, row_number() over (partition by id order by id) as seqnum
from table t
) t
where seqnum = 1;
The solution I have come up with is below.
It "feels" like a poor solution - I am still open to new answers:
SELECT
ID,
min(color),
min(feel),
min(size),
min(alive),
min(age)
FROM TableA
group by ID
I do not like how verbose I am with the application of the min function to every column, but this returns the desired result set.
I'm attempting to pull down records that are filtered by two date columns - I need to show all "active" records. Currently, I am able to pull records using the latest "effective date", but the problem is I may have active records across multiple effective dates.
An "active" record is defined as a record with an effective date prior to or equal to current date (see notes for current date assumptions), with an end date that is equal to or greater than current date. An "inactive" record would be the first and second rows of data in my example, an active record would be the third row of data.
I'm working with a data set similar to this:
+-------------+----------------+----------+---------+---------+---------+
| Mode Name | Effective Date | End Date | Mode ID | Param 1 | Param 2 |
+-------------+----------------+----------+---------+---------+---------+
| Single Mode | 20110102 | 20120313 | 1 | Green | Metal |
| Single Mode | 20120314 | 20131122 | 1 | Green | Wood |
| Single Mode | 20131123 | 29991231 | 1 | Orange | Plastic |
| Multi Mode | 20110102 | 20120313 | 5 | Orange | Plastic |
| Multi Mode | 20120314 | 20120501 | 5 | Red | Metal |
| Triple Mode | 20120314 | 20120314 | 3 | Blue | Cloth |
| Triple Mode | 20120315 | 20131122 | 3 | Red | Wood |
| Triple Mode | 20131123 | 20131130 | 3 | Red | Wood |
| Triple Mode | 20131201 | 29991231 | 3 | Orange | Wood |
| Double Mode | 20131123 | 29991231 | 2 | Green | Metal |
| Double Mode | 20131202 | 29991231 | 2 | Brown | Plastic |
| Quad Mode | 20131202 | 29991231 | 4 | Black | Wood |
| Quad Mode | 20131203 | 29991231 | 4 | Green | Plastic |
| Zero Mode | 20090704 | 29991231 | 0 | Blue | Cloth |
+-------------+----------------+----------+---------+---------+---------+
What I need to do is query so that each "active" mode is shown, but only the latest active mode as defined by the "effective date" column. "Ended" modes should not be shown. An "ended" mode is defined as having an end date prior to current date - with "29991231" being defined as "no end date". Ideally, the data set above would filter down to this:
+-------------+----------------+----------+---------+---------+---------+
| Mode Name | Effective Date | End Date | Mode ID | Param 1 | Param 2 |
+-------------+----------------+----------+---------+---------+---------+
| Single Mode | 20131123 | 29991231 | 1 | Orange | Plastic |
| Triple Mode | 20131201 | 29991231 | 3 | Orange | Wood |
| Double Mode | 20131202 | 29991231 | 2 | Brown | Plastic |
| Quad Mode | 20131203 | 29991231 | 4 | Green | Plastic |
| Zero Mode | 20090704 | 29991231 | 0 | Blue | Cloth |
+-------------+----------------+----------+---------+---------+---------+
Some notes:
Assume "current date" in this example is 2013-12-16.
You cannot filter on end date alone - as due to the way our system works, an end date of "29991231" does not guarantee a record is ended. For example, given two records with ending dates of "29991231", the one with the more recent effective date will supercede the one with an older effective date.
Some records will not be shown at all because they are ended prior to the current date.
This is an old system that is terribly designed. I'm sure there are ton of better ways to store data (believe me, what I'm showing you is NOT the worst part) - but unfortunately I'm stuck with what I have.
Here you go
SELECT
YourTable.ModeName,
YourTable.EffectiveDate,
YourTable.EndDate,
YourTable.ModeId,
YourTable.Param1,
YourTable.Param2
FROM
YourTable INNER JOIN
(SELECT
ModeName,
MAX(EffectiveDate) AS MaximumEffectiveDate
FROM YourTable AS YourTable_1
WHERE (GETDATE() BETWEEN CONVERT(Date, EffectiveDate, 101) AND CONVERT(Date, EndDate, 101))
GROUP BY ModeName) AS GroupedByMode ON YourTable.ModeName = GroupedByMode.ModeName AND
YourTable.EffectiveDate = GroupedByMode.MaximumEffectiveDate
Just change the GETDATE() with the date of your choice
Hopefully this is what you need, I copied your data and tested it to get the same results you have
You can use a CTE to get the single record for each:
with MaxDate as (select
[Mode Name],
max([Effective Date]) as mdate
from
table1
group by [Mode Name])
select
*
from
table1 t1
inner join
MaxDate on mdate = [Effective Date]
and t1.[Mode Name] = MaxDate.[Mode Name]
where [End Date] = 29991231
SQL Fiddle