sql select to extract and link the record above - sql-server-2008

I need some assistance with my extract. Below is a view of my data and how it is extract from a MS SQL database.
My challenge is that the database does not differentiate from the different "email address" . How do I link email address record to the record above.
Secid|Name|Question|Answer|
2|load1|Name of Principle|Joe Make|
2|load1|Contact Number|12234423|
2|load1|Email address|joemake#mymail.com|
2|load1|Name of Principle|Amy Soup|
2|load1|Contact Number of Principle|23134|
2|load1|Email address|amysoup#mymail.com|
2|load1|Name of Teacher|james blue|
2|load1|Contact Number|8787878|
2|load1|Email Address|jamesblue#mymail.com|
2|load1|Name of Secretary|CHARLES black|
2|load1|Contact Number|989897|
2|load1|Email Address|chblack#mymail.com|

If you don't have any column to order by (e.g. a monotonically increasing identity column, or a timestamp), I'm afraid you're honestly out of luck. There is no way to guarantee any sort of ordering of the rows for any query.
What you can do, however, is export the data into an Excel sheet and then look at it manually and put the rows in the right order, assuming you can figure it out. Unfortunately this is really going to be the only way.
If you had a column you could order by, you can use a join to group the rows, assuming you had a way of identifying the start of each set - in your case a Question like 'Name of %' should probably work. Assuming an identity column called Id, something like:
select t.*, tGroupStart.Id as GroupId
from myTable t
join myTable tGroupStart on tGroupStart.Id <= t.Id
and tGroupStart.Question like 'Name of %'
where not exists (
select 1
from myTable t2
where t2.Id <= t.Id
and t2.Question like 'Name of %'
and t2.Id > tGroupStart.Id
)

Related

Get Conditionally Latest record from each group - without Aggregate functions or Partition

I have been trying to do this in many ways suggested.
Note: we do not want aggregate function or Partition since this is just a small part of whole Stored procedure and this is client requirement to not have it, so not in option and not possible duplicate of other existing answers / questions
I have a messages table, which has a column from and to, a foreign key to the user table, basically which user sends to whom at simplest. I also have other columns which are isSnoozed and snoozeAt for if the message is snoozed.
So the ordering is according to case. If messages is snoozed then consider snoozeAt time to Order or if not then consider sendAt. (right now we can ignore this condition while ordering, But I mentioned this since we cannot take simply MAX(id) )
I need to get recent most message from messages group by from user id
messages table like :
id -- to -- from -- isSnoozed -- snoozedAt -- sendAt ...
What I tried :
select * from ( select * from messages order by sendAt DESC) as TEMP GROUP BY TEMP.from
I tried many similar approaches but none worked.
I wasted many paid hours but can't find an approach which meets my exact requirement
NOTE: Please ignore typo in query if any, since I cant type in exact query table and names, So i typed in directly here
I figured this out by doing something like this, which could be explained in a simplified way:
select * from message where message.id in (
select
( select id from message where message.from = user.id order by CASE isSnoozed WHEN 0 THEN sendAt ELSE snoozeAt END DESC limit 1) as id
from user where user.id in ( select friends.`whoIsAdded` from friends where friends.`whoAdded` = myId)
) order by CASE isSnoozed WHEN 0 THEN sendAt ELSE snoozeAt END DESC
If I understand correctly, you just want the largest value in one of two columns. Assuming the values are never NULL, you can use greatest():
select m.*
from messages m
where greatest(m.sendAt, m.snoozedAt) =
(select max(greatest(m2.sendAt, m2.snoozedAt))
from messages m2
where m2.from = m.from
);
If the columns can be NULL, then you can use coalesce() to give them more reasonable values.

insert a table record into another table

I want to insert a table record into another table. I am selecting user id ,date and variance. When i insert the data of one user it works fine but when i insert multiple records it gives me an error of SQL Error [1292] [22001]: Data truncation: Truncated incorrect time value: '841:52:24.000000'.
insert into
features.Daily_variance_of_time_between_calls(
uId,
date,
varianceBetweenCalls)
SELECT
table_test.uid as uId,
SUBSTRING(table_test.date, 1, 10) as date ,
VARIANCE(table_test.DurationSinceLastCall) as varianceBetweenCalls #calculating the vairiance of inter-event call time
FROM
(SELECT
id,m.uid, m.date,
TIME_TO_SEC(
timediff(m.date,
COALESCE(
(SELECT p.date FROM creditfix.call_logs AS p
WHERE
p.uid = m.uid
AND
p.`type` in (1,2)
AND
(p.id < m.id AND p.date < m.date )
ORDER BY m.date DESC, p.duration
DESC LIMIT 1 ), m.date))
) AS DurationSinceLastCall,
COUNT(1)
FROM
(select distinct id, duration, date,uid from creditfix.call_logs as cl ) AS m
WHERE
m.uId is not NULL
AND
m.duration > 0
# AND
# m.uId=171
GROUP BY 1,2
) table_test
GROUP BY 1,2
If i remove the comment it works fine for one specific user.
Let's start with the error message:
Data truncation: Truncated incorrect time value: '841:52:24.000000'
This message suggests that at some stage MySQL is running into a value which it cannot convert to a date/time/datetime. Efforts in isolating the issue should therefore begin with a focus on where values are being converted to those data types.
Without knowing the data types of all the fields used, it's difficult to say where the problem is likely to be. However, once we knew that the query on it's own ran without complaint, we also then knew that the problem had to be with a conversion happening during the insert itself. Something in the selected data wasn't a valid date, but was being inserted into a date field. Although dates and times and involved in your calculation of varianceBetweenCalls, variance itself returns a numeric data type. Therefore I deduced the problem had to be with the data returned by SUBSTRING(table_test.date, 1, 10) which was being inserted into the date field.
As per the comments, this turned out to be correct. You can exclude the bad data and allow the insert to work by adding the clause:
WHERE
table_test.date NOT LIKE '841%'
AND table_test.DurationSinceLastCall NOT LIKE '841%' -- I actually think this line is not required.
Alternatively, you can retrieve only the bad data (with a view to fixing it), by removing the INSERT and using the clause
WHERE
table_test.date LIKE '841%'
OR table_test.DurationSinceLastCall LIKE '841%' -- I actually think this line is not required.
or better
SELECT *
FROM creditfix.call_logs m
WHERE m.date LIKE '841%'
However, I'm not sure the data type of that field, so you may need to to it like this:
SELECT *
FROM creditfix.call_logs m
WHERE SUBSTRING(m.date,10) LIKE '841%'
Once you correct the offending data, you should be able to remove the "fix" from your INSERT/SELECT statement, though it would be wise to investigate how the bad data got into the system.

using subselect in mysqli

I have a query which works currently, but we added more the possibility of one customer doing more than one test drive. this additional test Drive is on a different table. The customer ID is an auto increment number on the testdriveform table. So I need to check for addition entries, based on the customer id from table 1 in table 2 and list them along withe the rest.
SELECT * FROM testdriveform Where SalesAgent not like '%Test%' and SalesAgent like '%$Sales%' and Date between '$sDate' and '$eDate' and Stock != '' order by Date, SalesAgent;
I need to add a subselect I think. Something that adds
SELECT * FROM testdrives WHERE custID = testdriveform.id
phpmyadmin is down on bluehost..again. Anyone?
NO, you don't need a subselect; rather need a JOIN between the tables like
SELECT td.*, tdf.*
FROM testdriveform tdf
JOIN testdrives td ON td.custID = tdf.id
Where tdf.SalesAgent not like '%Test%'
and tdf.SalesAgent like '%$Sales%'
and tdf.`Date` between '$sDate' and '$eDate'
and tdf.Stock != ''
order by tdf.`Date`, tdf.SalesAgent;

SQL Union All alias from first table?

I have two tables
[data] - title,maker,partnum,price
[cross] - product(data.partnum),title,maker,partnum,price
What I want is listing all product via sysn number. How can I get with union all data like that with ordering ->
[data table] Microsoft, "some note", 9989, $20
[cross table] Microsoft reseller, "some note", 1045, $30
[cross table] Apple reseller in Microsoft :), "some note", 2233, $40
virtual spacer :)
[data table] Microsoft, "some note", 9989, $10
[cross table] Lenovo reseller in Microsoft..
Im trying with this
SELECT `title`,'Microsoft' AS `maker`,`partnum`,`price`
FROM data as d
WHERE sysn=%s
GROUP BY partnum
UNION ALL
SELECT `title`,`maker`,`partnum`,`price`
FROM cross as c
WHERE c.product=d.partnum
GROUP BY `partnum`
Thanks
It's not entirely clear what you are asking. Consider setting up an example schema and data in http://sqlfiddle.com.
A "virtual spacer" is going to be very messy to achieve. It's not totally impossible, just messy.
For returning rows in a particular sequence, you are going to need to add an ORDER BY clause.
It's not at all clear why you are including GROUP BY clauses. The GROUP BY on the first SELECT would effectively "collapse" example output rows 1. and 5. given the same value 9989 for partnum. Absent an explanation of why you need a GROUP BY, I'm going to guess that what you really intended was an ORDER BY clause.
It's also not clear why the literal value 'Microsoft' would need to appear in the SELECT list, in place of the maker column from the data table. There's nothing invalid SQL-wise with doing that. But absent an explanation, it just doesn't make much sense.
The question we should to ask... Why is this specific result needed? Is there a different result which would be easier to achieve, which would equally satisfy the requirements?
Setting aside the "virtual spacer" row, the return from a query like this seems like it satisfies most of the specification:
SELECT t.src
, t.title
, t.maker
, t.partnum
, t.price
FROM (
SELECT '[data]' AS `src`
, d1.title AS `title`
, d1.maker AS `maker`
, d1.partnum AS `partnum`
, d1.price AS `price`
, d1.partnum AS `product`
FROM data d1
WHERE d1.sysn = ?
UNION ALL
SELECT '[cross]'
, c2.title
, c2.maker
, c2.partnum
, c2.price
, c2.product
FROM cross c2
JOIN data d2
ON d2.partnum = c2.product
WHERE d2.sysn = ?
)
ORDER BY t.product DESC, t.src DESC, t.price ASC
If you are using MySQL, "cross" is a reserved word and you must enclose cross in backticks to use it as a table name (The backtick is next the the '1' on the keyboard on the upper left).

SQL: have duplicates for each ID, I would like to keep the ID with site that is not blank

ID Site
a www.google.com
a
b www.qq.com
b
c www.hodes.com
.
.
.
I have a table like the one above, I'd like to extract the the site value is not blank, such as:
ID Site
a www.google.com
b www.qq.com
c www.hodes.com
You just have to check if the content of the column site is null or not. In order to select the rows with content:
SELECT * FROM TABLE_NAME WHERE SITE IS NOT NULL
Read more here.
select * from table where Site <> '' or Site is not null
will work if the blank ones are ALWAYS duplicates.
otherwise
select max(id), max(site) from table group by id
Should be okay
select
ID,
max(if(trim(site) = '', null, site)) as site
from tbl
group by ID
;
You could substitute GROUP_CONCAT for max if more than one site per ID.
I'm gonna go on a limb and assume that you want to remove the empty rows from your database. If that's not the case, just move the where clause to a Select statement.
Delete from TableName where ISNULL(Site, '')=''
If you must return one and only one record per id, then your code must
cope with potential multiple records per id -- and you need the max() and group by .
I would suggest:
Select id, max(site)
from table_name
where nvl(site,0) <> 0
group by id
Else if you know that you'd never encounter multiple records with the same id:
Select id, site
from table_name
where nvl(site,0) <> 0