Enumerate field from existing records in cakePHP - cakephp-2.0

I work with cakePHP and have database table with 3 columns: ID, Name, OrderNo
ID is the primary key which is defined as autoincrement field and contains a number.
Name is a user given value
OrderNo contains a numeric value which is used for sorting SELECT result (ORDER BY ...)
Now, the OrderNo Field is needed because the user have the right, change the order. So far, no problem. If the record on the 4 place on the result should switch the position with the record on place 8, I only flip the value in the field OrderNo and the next result will return the new ordered list.
But now, there is a situation where simply updating will result in a long execution time when I've many records:
When I delete a record, a "place" will be freed. I want close the gap and want enumerate all fields starting with 0.
Sample records;
ID, Name, OrderNo
==================
1, Name1, 5
2, Name2, 4
3, Name3, 3
4, Name4, 2
5, Name5, 1
I remove ID 3 which results in
ID, Name, OrderNo
==================
1, Name1, 5
2, Name2, 4
4, Name4, 2
5, Name5, 1
Which should be
ID, Name, OrderNo
==================
1, Name1, 4
2, Name2, 3
4, Name4, 2
5, Name5, 1
Currently I would loop all existing records (sorted by OrderNo) and would write the field OrderNo with a value which I would increase every round but this solution isn't really efficient. I tested it with 5000 records and it tooks 40 seconds to finish.
Is there maybe a cakePHP solution based on sql syntax which can do that job much more faster?

Maybe the tree behavior is what you looking for. http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html

Related

How to update rows based on one field/column on two tables

I want to update one table using another table on field "Id" such that it wont create duplicates
let say my first table is Table1 and second table is Table2 . I would like to update the row in Table1 from Table2 when the Id is matching
I am aware of using UNION function but this applies to entire columns where I only need to consider a single column. https://docs.snowflake.com/en/sql-reference/operators-query.html#union-all
Example of my Tables
Table1
Id name number value
1 a 8 100
2 b 8 100
3 c 8 100
4 d 8 100
Table2
Id name number value
3 c 8 99
4 d 6 100
5 e 7 100
Expected output
Id name number value
1 a 8 100
2 b 8 100
3 c 8 99
4 d 6 100
5 e 7 100
Please note that in the output table row with Id 3,4 has be updated and new Id 5 is inserted.
PS: It would be better if someone could provide me the select statement to get the output table.
The constuct you are searching for is called MERGE:
CREATE OR REPLACE TABLE trg(Id INT, name VARCHAR, number INT, value INT)
AS SELECT 1 ,'a', 8, 100
UNION SELECT 2 ,'b', 8, 100
UNION SELECT 3 ,'c', 8, 100
UNION SELECT 4 ,'d', 8, 100;
CREATE OR REPLACE TABLE src(Id INT, name VARCHAR, number INT, value INT)
AS SELECT 3 ,'c', 8, 99
UNION SELECT 4 ,'d', 6, 100
UNION SELECT 5 ,'e', 7, 100;
Query:
MERGE INTO trg
USING src
ON trg.Id = src.Id
WHEN MATCHED THEN UPDATE SET name = src.name,
number = src.number,
value = src.value
WHEN NOT MATCHED THEN INSERT (ID, name, number, value)
VALUES (src.Id, src.name, src.number, src.value);
SELECT * FROM trg;
Output:
EDIT:
PS: It would be better if someone could provide me the select statement to get the output table.
UNION ALL combined with QUALIFY could be used:
WITH cte AS (
SELECT *, 1 AS priority FROM trg
UNION ALL
SELECT *, 0 AS priority FROM src
)
SELECT Id, Name, Number, Value
FROM cte
QUALIFY ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Priority) = 1
ORDER BY Id;

Count new items tried each day without including those tried on previous days - Using PostgreSQL

How to get count of new unique items tried each day (this shouldn't include items that were already tried previously) - Using PostgreSQL
Input:
Date
Order-ID
Item
05-04-21
1
Apple
05-04-21
2
Orange
05-04-21
3
Apple
06-04-21
4
Apple
06-04-21
5
Banana
06-04-21
6
Orange
07-04-21
7
Apple
07-04-21
8
Banana
07-04-21
9
Orange
Desired Output:
Date
New Items
05-04-21
2
06-04-21
1
07-04-21
0
On 06-04-21, 1 new item was tried - counts only Banana since Apple & Orange were tried previously on 05-04-21 and so on...
There are several steps to achieve what you looking for. The following walks through each of those steps. Some steps could possible be combined, but not here. This will not necessarily be the shortest query available. But the goal is not to produce the shortest query, but to show the a think process and working in sets.
Eliminate any duplicate items for a single day. ( reduce Apple on
05/24 to 1).
Eliminate any item from a date where that item occurs is a prior
date.
Count the number of items remaining for each date.
From the original data get each day testing was done.
For each date in #4 get the number of items remaining from #3, if
none show 0.
Order the final result.
See Demo
with items (ord_date, order_id, item) as -- 0 Define test data instead of actual table
( values (date '2021-05-04', 1, 'Apple')
, (date '2021-05-04', 2, 'Orange')
, (date '2021-05-04', 3, 'Apple')
, (date '2021-06-04', 4, 'Apple')
, (date '2021-06-04', 5, 'Banana')
, (date '2021-06-04', 6, 'Orange')
, (date '2021-07-04', 7, 'Apple')
, (date '2021-07-04', 8, 'Banana')
, (date '2021-07-04', 9, 'Orange')
)
-- your query starts here
-- get date and number of items remaining
select idt.ord_date "date", coalesce(s2.cnt,0) "items" -- 5
from ( get each date having orders/items -- 4
select distinct ord_date
from items
) idt
left join (-- for each date count the number of items
select ord_date, count(*) cnt -- 3
from (-- reduce th just 1 row per item per day
select distinct on (ord_date, item) -- 1
ord_date, item
from items
order by ord_date, item
) s
where not exists ( -- elminate items with checked on a prior day -- 2
select null
from items i
where i.item = s.item
and i.ord_date < s.ord_date
)
group by s.ord_date
) s2
on ( s2.ord_date = idt.ord_date)
order by idt.ord_date; -- 6 final ordering

GoogleSheets: Screen a Column for IDs and return associated cells (multiple occurrences)

Essentially I have a data-structure like this (hundreds of rows, constantly updated):
ID
Date
Value
1000
date1
value 1
1001
date2
value 2
1002
date3
value 3
1001
date4
value 4
1003
date5
value 5
where
IDs are unique but can occur multiple times
Dates indicate when IDs were created or their values updated
Values are not unique
What I want to do is to search the ID row and get the date&value associated with it. IF the same ID occurs again, it should be listed in the same row, e.g.
ID
Date
Value
1000
date1
value 1
1001
date2
value 2
date 4
value 4
1002
date3
value 3
1003
date5
value 5
Ideally, this is done using an array. Like I said, the list is constantly updated so dragging a formula like:
=TRANSPOSE(FILTER($A$2:$A, $B$2:$B = A2))
isn't really an option...
Any thoughts? Help would be greatly appreciated!!
Cheers
try:
=ARRAYFORMULA(IFNA(VLOOKUP(A2:A&"×"&
COUNTIFS(A2:A, A2:A, ROW(A2:A), "<="&ROW(A2:A)), {A2:A&"×"&
COUNTIFS(A2:A, A2:A, ROW(A2:A), "<="&ROW(A2:A))-1, B2:C}, {2, 3}, 0)))
update:
=ARRAYFORMULA(SUBSTITUTE(TRIM(SPLIT(FLATTEN(QUERY(TRANSPOSE(QUERY(QUERY(
IF(A2:A="",,{A2:A&"×", TO_TEXT(B2:B)&"×"&C2:C&"¤×", ROW(A2:A)&TO_TEXT(B2:B)&"×"&C2:C&"¤×"}),
"select Col1,max(Col2) where Col1 is not null group by Col1 pivot Col3"),
"offset 1", 0)),,9^9)), "×")), "¤", ))
demo spreadsheet

MSSQL selecting distinct ID based on set of parameters

I'm sure this is simple, but it's been a rough day:
I have a table of data like below. I have a list of attribute IDs and need to get the distinct ProductID that matches all the AttributeIDs selected.
ProductID AttributeID
1 2
1 3
1 5
2 2
2 3
2 7
As an example, I want the distinct product ID that matches attributes 2, 3, AND 5.
What's the most optimal way to do this?
using count(distinct ) = n where n is the number of elements in the where AttributeId in () list.
select ProductId
from t
where AttributeId in (2,3,5)
group by ProductId
having count(distinct AttributeId)=3

How to select top 3 maximum values from SQL Server column

I have values in SQL Server derived column sorted as descending i.e.
id Count OR id Count OR id Count
1 4 1 5 1 11
2 4 2 2 2 1
3 4 3 1 3 1
4 4 4 1 4 1
5 4 5 1 5 1
Now I want to select top 3 maximum values. How can I select so that query returns consistent result every time.
For example if values of Count are same which id's should be returned as top 3 maximums, similarly if 3rd value is matched with other values and if 2nd value is matched with other values then which id's should be returned by the query. And the result should be consistent every time I execute the query.
The with ties argument of the top function will return all the of the rows which match the top values:
select top (3) with ties id, count from table1
order by count desc
Alternatively, if you wanted to return 3 values only, but make sure they are always the same 3 values, then you will need to use something else as a tie-breaker. In this case, it looks like your id column could be unique.
select top (3) id, count from table1
order by count desc, id

Resources