MySQL Select query - Sorting data based on date - c#

I'm using MySQL.
This is table name item_supplier
supplier_ID Item_ID Date Price QTY
1 1 2012-01-01 00:00:00 500.00 2
1 1 2012-01-03 00:00:00 450.00 10
2 1 2012-01-01 00:00:00 400.00 5
3 1 2012-05-01 00:00:00 500.00 1
I need a select query showing a table something like this.
supplier_ID 2012-01-01 2012-01-03 2012-05-01
1 500.00(2) 450.00(10) null
2 400.00(5) null null
3 null null 500.00(1)
or, at least,
supplier_ID 2012-01-01 2012-01-03 2012-05-01
1 500.00 450.00 null
2 400.00 null null
3 null null 500.00
I hope someone can help me on this or give me a hint.

If there aren't a finite number of dates that are known beforehand, then you can't do what you want in MySQL alone.
Your best bet is to get a table like:
+---------+------------+-------------+-------------+
| Item_ID | Date | supplier_ID | price |
+---------+------------+-------------+-------------+
| 1 | 2012-01-01 | 1 | 500.00 (2) |
| 1 | 2012-01-01 | 2 | 400.00 (5) |
| 1 | 2012-01-03 | 1 | 450.00 (10) |
| 1 | 2012-05-01 | 3 | 500.00 (1) |
| ... | ... | ... | ..... |
Which can be done with:
SELECT Item_ID,Date,supplier_ID,CONCAT(FORMAT(Price,2),' (',QTY,')') AS price
FROM item_supplier
ORDER BY Item_ID,Date,supplier_ID;
Then on the C# side, loop through the results and print your desired output.
Since the output is now sorted by Item_ID, Date, and then supplier_ID, it's simple to loop through the results and then output in the format you want.

First of My SQL does not support to Crosstab/Pivot Query. So you need to create Dynamic temp Table for Columns and then inset record into it.
Like, First you have to fetch all date in one cursor and then create temp table and insert columns based on date's Cursor . After Creating table create another cursor for inserting rows. and fetch every row and update temp table.I have also done this using this way....
If you have any query please contact.

Related

How to combine Duplicate data into single Data MySql

I was wondering if what is this called or is this even possible in MySql, or what should I do to achieve this. This is what Mysql Table Looks Like:
Desired Output:
you can use a query like this:
SELECT customerid
, CONCAT( SUM(CAST(item as INTEGER)), 'pcs,', SUBSTRING_INDEX(item, ',', -1) ) as item
FROM myitems
GROUP BY SUBSTRING_INDEX(item, ',', -1);
Sample
MariaDB [bernd]> SELECT * FROM myitems;
+----+------------+---------------+
| id | customerid | item |
+----+------------+---------------+
| 1 | 15 | 7pcs, Car |
| 2 | 15 | 2pcs, Car |
| 3 | 15 | 3pcs, Engine |
| 4 | 15 | 2pcs, Engine |
| 5 | 15 | 5pcs, Exhaust |
+----+------------+---------------+
5 rows in set (0.07 sec)
MariaDB [bernd]> SELECT customerid
-> , CONCAT( SUM(CAST(item as INTEGER)), 'pcs,', SUBSTRING_INDEX(item, ',', -1) ) as item
-> FROM myitems
-> GROUP BY SUBSTRING_INDEX(item, ',', -1);
+------------+---------------+
| customerid | item |
+------------+---------------+
| 15 | 9pcs, Car |
| 15 | 5pcs, Engine |
| 15 | 5pcs, Exhaust |
+------------+---------------+
3 rows in set, 5 warnings (0.02 sec)
MariaDB [bernd]>
Your table structures wont allow (anything near as easy). A better format of your table might be more like
id customerid item qty
1 15 Car 7
2 15 Car 2
3 15 Engine 3
4 15 Engine 2
5 15 Exhaust 5
Then, you could get what you are looking for easily such as
select
t.customerid,
t.item,
sum( t.qty )
from
YourTable t
group by
t.customerid,
t.item
This WOULD give your your
customerid item qty
15 Car 9
15 Engine 5
15 Exhaust 5
Having a properly formatted table vs trying to have a description requires parsing numeric values vs rest of description is never a good solution such as what you have here. Too many opportunities for bad answers.

How do I remove rows from a DataTable up to a certain date?

I am having trouble filtering a DataTable, say DtFromExcel. The DataTable does NOT have a header row, and it starts with an actual data row, and it looks something like the following.
1 | 05/01/2020 Fri | ABC | XYZ | ...
2 | 05/01/2020 Fri | AAA | WKV | ...
3 | 05/02/2020 Sat | BCD | OPQ | ...
4 | 05/03/2020 Sun | CDE | RST | ...
5 | 05/03/2020 Sun | EFA | FAY | ...
6 | 05/03/2020 Sun | AXG | EAS | ...
7 | 05/04/2020 Mon | DEF | LMN | ...
8 | 05/04/2020 Mon | SXA | YTR | ...
9 | 05/05/2020 Tue | DAF | AAG | ...
The second column contains a certain date with some extra string (day of the week), and these rows are ordered by this date column. There can be multiple rows with the same date.
Now, I want to delete rows where the date column contains a certain date AND any rows prior to that. For example, if the certain date is 05/04/2020, then I need to delete all rows up to the 8th row, so that the remaining DataTable would have to look like
9 | 05/05/2020 Tue | DAF | AAG | ...
My problem is, first I don't know how to filter the DataTable without the column name. I thought about assigning a header row without overwriting the first actual data row, but it seems like this is a lot of work, only to filter. Second, I am not sure how to use these conditions ((a)the second column contains a certain date, AND (b)any row with the dates prior to that certain date).
private void DeleteRows(DateTime certainDate){
DataRow[] targetRowsToDelete = dtFromExcel.Select(/* Not sure what to put in here */);
foreach (DataRow row in targetRowsToDelete)
{
if (Convert.ToDateTime(row[1].ToString().Split(c" ")[0]) <= certainDate)
DtFromExcel.Rows.Remove(row);
}
}
I did not want to loop through the whole DataTable because this process occurs often in my program.
If you use the empty constructor to create a DataColumn with no name, the documentation states...
When created, a DataColumn object has no default ColumnName or Caption. When you add it to a DataColumnCollection, a default name ("Column1", "Column2", and so on) will be generated if a name has not been assigned to the ColumnName.
...so creating and loading a DataTable like this...
const string Input = #"1 | 05/01/2020 Fri | ABC | XYZ | ...
2 | 05/01/2020 Fri | AAA | WKV | ...
3 | 05/02/2020 Sat | BCD | OPQ | ...
4 | 05/03/2020 Sun | CDE | RST | ...
5 | 05/03/2020 Sun | EFA | FAY | ...
6 | 05/03/2020 Sun | AXG | EAS | ...
7 | 05/04/2020 Mon | DEF | LMN | ...
8 | 05/04/2020 Mon | SXA | YTR | ...
9 | 05/05/2020 Tue | DAF | AAG | ...";
DtFromExcel = new DataTable();
for (int i = 0; i < 5; i++)
{
DataColumn column = new DataColumn();
Console.WriteLine($"Column {i} has ColumnName \"{column.ColumnName}\"");
DtFromExcel.Columns.Add(column);
Console.WriteLine($"Column {i} has ColumnName \"{column.ColumnName}\"");
}
foreach (string line in Input.Split("\r\n"))
{
string[] fields = line.Split(" | ");
DtFromExcel.Rows.Add(fields);
}
...produces this output...
Column 0 has ColumnName ""
Column 0 has ColumnName "Column1"
Column 1 has ColumnName ""
Column 1 has ColumnName "Column2"
Column 2 has ColumnName ""
Column 2 has ColumnName "Column3"
Column 3 has ColumnName ""
Column 3 has ColumnName "Column4"
Column 4 has ColumnName ""
Column 4 has ColumnName "Column5"
...so you could always use those default names. Further, just because your input data doesn't specify column/field names doesn't mean you can't do so after it's been loaded into the DataTable...
DtFromExcel.Columns[1].ColumnName = "MyDateColumn";
Either way, you'll have a known name by which you can refer to that column.
As to your comment about not wanting to "loop through the whole DataTable", it's not clear if you mean because of the additional code or perhaps performance implications, but to the latter point even if you don't explicitly loop through and test every DataRow, Select() will. On that note, since you say the rows are ordered by date, you can exploit that using LINQ to stop scanning rows as soon as a date outside the search range is found...
private static DateTime GetRowDate(DataRow row) => DateTime.ParseExact(
(string) row["MyDateColumn"], "MM/dd/yyyy ddd", null
);
private void DeleteRows(DateTime maxDate)
{
DataRow[] rowsToRemove = DtFromExcel.AsEnumerable()
.TakeWhile(row => GetRowDate(row) <= maxDate)
.ToArray();// Required to prevent "Collection was modified" exception in foreach below
foreach (DataRow row in rowsToRemove)
DtFromExcel.Rows.Remove(row);
}
If your rows aren't guaranteed to be sorted by date, then you can substitute Where() for TakeWhile() and it will work just the same.
As for your original request to use DateTable.Select(), I'm not sure if that's even feasible here since your dates appear to be stored as string, not DateTime, in your DataColumn. I see that the expression syntax supports a CONVERT() function that can convert between String and DateTime, but I can't imagine that would be any more performant or readable than LINQ so I wouldn't pursue that unless you absolutely have to.

Oracle Recursion

I want list all SOURCE_ID if the source has destination, the query below not work probably !!
select SOURCE_ID,
LINK_TYPE,
DESTINATION_ID
from LINK_TABLE
where link_table.link_type=1
and link_table.destination_is_deleted=0
START WITH link_table.source_id='100'
CONNECT BY PRIOR link_table.source_id=link_table.destination_id
Sample data
SOURCE_ID | DESTINATION_ID | LINK_TYPE| DESTINATION_IS_DELETED|
----------|-----------------|----------|-----------------------|
100 | 1500 | 1 | 0 |
100 | 1200 | 1 | 0 |
100 | 1300 | 1 | 1 |
1500 | 600 | 1 | 0 |
1500 | 700 | 1 | 0 |
700 | 88 | 1 | 0 |
Assuming you want to walk the hierarchy from the root nodes to the leaves this is what you need:
select SOURCE_ID,
LINK_TYPE,
DESTINATION_ID
from LINK_TABLE
where link_table.link_type=1
and link_table.destination_is_deleted=0
START WITH link_table.source_id='100'
CONNECT BY PRIOR link_table.destination_id = link_table.source_id
/
It's just a matter of swapping the referenced columns in the CONNECT BY PRIOR clause. Unfortunately the Oracle syntax is not intuitive here: I've been using it for over twenty years and I still have to test a query to make sure I've got them the right way round :)
I changed the query structure to solve the issue.
select SOURCE_ID,DESTINATION_ID,link_table.source_class,link_table.linktype,link_table.destination_class
from LINK_TABLE
where (link_table.source_id in( select link_table.DESTINATION_ID from link_table where link_table.source_id='100'and link_table.linktype=1 and link_table.destination_isdeleted=0 ))
and (link_table.linktype=1) or (link_table.source_id='100')

How can i get the sum of a database table to a variable?

I have a database table named Deposit and one of the column name in it is 30-12-2013. The column has two values such as 54,26.
i want to get the sum of that column column into a variable. I use the following code:
con.Open();
SqlCeCommand cmd11 = con.CreateCommand();
cmd11.CommandText = "select sum(30-12-2013) from Deposit";
int result = ((int)cmd11.ExecuteScalar());
displaylabel.Text = result.ToString();
con.Close();
But, I am getting the value of variable 'result' as -3990.
Whats wrong with my code.. Please help me.. Thanks in advance..
(30-12-2013) * 2 (because you have two entries) = -1995 * 2 = -3990
You have to use:
SELECT sum([30-12-2013])
FROM dbo.Deposit
This has already been answered so instead of answering your actual question I am going to propose an alternative solution.
Instead of having a table as follows:
SomeColumn | 30-12-2013 | 31-12-2013 | 01-01-2014
-----------+------------+------------+------------
A | 540 | 100 | 246
B | 130 | 90 | 377
Have a normalised table:
SomeColumn | Date | Amount
-----------+------------+--------
A | 2013-12-30 | 540
A | 2013-12-31 | 100
A | 2014-01-01 | 246
B | 2013-12-30 | 130
B | 2013-12-31 | 90
B | 2014-01-01 | 377
This means you don't require a new column for every day. So your query would become:
SELECT SUM(Amount) AS Amount
FROM Deposit
WHERE Date = '20131230';
And if you wanted to reproduce your original structure you can use:
SELECT SomeColumn,
SUM(CASE WHEN Date = '20131230' THEN Amount ELSE 0 END) AS [30-12-2013],
SUM(CASE WHEN Date = '20131231' THEN Amount ELSE 0 END) AS [31-12-2013],
SUM(CASE WHEN Date = '20140101' THEN Amount ELSE 0 END) AS [01-01-2014]
FROM Deposit
GROUP BY SomeColumn;
Example on SQL Fiddle (Using SQL Server as it doesn't support SQL Server CE)
Try to use brackets for columns with unusual names -
cmd11.CommandText = "SELECT SUM([30-12-2013]) FROM Deposit";

How to rewrite SQL query to LINQ (using GroupBy, Distinct)

I have a question on mind for a few long days.
Finally, I made a SQL query, which I want to show in MVC4 View.
I build following SQL query:
select distinct date, max(priority) from Timetables where date between '2013-12-01' and '2013-12-31' group by date
which returns me a collection of dates and max priorities of that dates. That is OK for me. I am totaly okay, when this query returns me a whole Timetables record.
But I need to pass result of this query to View engine of MVC4.
I had some tries, but I am nowhere near finding a result for that.
If you have some other possibilities, how to do that, I am eager to hear :)
Also, I am using an Entity Framework.
Thanks!
e:
The database looks like that:
id | doctor_id | nurse_id | date | start_time | end_time |time_for_pacient| priority |comments
-----------------------------------------------------------------------------------------
1 | 5 | 4 | 13-12-01| 07:00 | 11:30 | 00:20 | 1 |Normal
2 | 5 | 4 | 13-12-02| 07:00 | 11:30 | 00:20 | 1 |Normal
3 | 5 | 4 | 13-12-01| 08:00 | 10:30 | 00:20 | 2 |Shorten
4 | 5 | 4 | 13-12-02| 06:00 | 10:30 | 00:10 | 3 |Extra
the result I want to achieve in View:
id | doctor_id | nurse_id | date | start_time | end_time |time_for_pacient| priority |comments
-----------------------------------------------------------------------------------------------------
3 | 5 | 4 | 13-12-01| 08:00 | 10:30 | 00:20 | 2 |Shorten
4 | 5 | 4 | 13-12-02| 06:00 | 10:30 | 00:10 | 3 |Extra
I just want to show a single record for each day with highest priority.
With EntityFramework and other ORM tools, don't think of selecting specific fields or columns. Rather, you're selecting specific obejcts.
To translate your exact query to LINQ would actually end up returning a collection of anonymous objects which is rarely what you want.
In C#, it might look like this:
var date1 = new Date(2013, 12, 1);
var date2 = new Date(2013, 12, 31);
var timetables = DbContext.Timetables
.Where(x => x.Date.CompareTo(date1) >= 0 && x.Date.CompareTo(date2) <= 0)
.Distinct();

Categories

Resources